代码之家  ›  专栏  ›  技术社区  ›  Denis Balko

通过将类作为函数参数传递以调用类方法的快速依赖项注入

  •  2
  • Denis Balko  · 技术社区  · 7 年前

    我可能用了错误的方法,但我想引入依赖注入来进行单元测试,为了做到这一点,我需要传递一个类作为参数。在某种程度上,伪代码应该如下所示:

    protocol LocalSavingProtocol {
        static func saveDataLocally()
    }
    
    class ProductionClass: LocalSavingProtocol {
        static func saveDataLocally() {
            print("actually save data")
        }
    }
    
    class TestClass: LocalSavingProtocol {
        static func saveDataLocally() {
            print("test saving data")
        }
    }
    
    func saveEverywhere(injecting localSavingClass: LocalSavingProtocol = ProductionClass) {
        localSavingClass.saveDataLocally()
    }
    
    //production code
    saveEverywhere()
    
    //test
    saveEverywhere(injecting: TestClass)
    

    很明显,这不起作用,尽管我试着传球 .Type .self ,更改 saveEverywhere 功能到

    saveEverywhere<T: LocalSavingProtocol>(injecting localSavingClass: T)
    

    以此类推,什么都没起作用。

    目标是建立一个系统,以便:

    1. 我可以在测试代码时注入一个类
    2. 我不必在生产代码中注入类(即存在默认值)
    3. 我可以在注入的类上调用类方法
    2 回复  |  直到 7 年前
        1
  •  4
  •   Gi0R    7 年前
    protocol LocalSavingProtocol {
        static func saveDataLocally()
    }
    
    class ProductionClass: LocalSavingProtocol {
        class func saveDataLocally() {
            print("actually save data")
        }
    }
    
    class TestClass: LocalSavingProtocol {
        class func saveDataLocally() {
            print("test saving data")
        }
    }
    
    func saveEverywhere(injecting localSavingClass: LocalSavingProtocol.Type = ProductionClass.self) {
        localSavingClass.saveDataLocally()
    }
    
    //production code
    saveEverywhere()
    
    //test
    saveEverywhere(injecting: TestClass.self)
    
        2
  •  -1
  •   tktsubota    7 年前

    依赖注入不涉及传入类,它注入了其他对象可以依赖的对象,因此 依赖关系 。这对单元测试有用的原因是您可以将代码封装到单独的对象中。

    您正在尝试从类型访问实例方法。依赖注入不需要传入类类型。而是传入对象:

    saveEverywhere(injecting: TestClass())
    

    对于默认值,还可以使用对象:

    func saveEverywhere(injecting localSavingClass: LocalSavingProtocol = ProductionClass()) {
    

    请注意 () 在这两个示例中。