dtsjq28482 2018-09-08 22:01
浏览 9

如何测试创建和注入依赖项的功能

My question is how do you decide where to inject a dependency, and how do you test the function in which the dependency is first injected into a function?

For example, I'm refactoring some Go code to use dependency injection with the goal of having the code be more testable.

This is what my refactored code looks like:

type FooIface interface {
  FooFunc()
}

type Foo struct {}

func (f *Foo) FooFunc() {
  // Some function I would like to stub
}

func main() {
  OuterFunction()
}

func OuterFunction() {
  fooVar := &Foo{}
  InnerFunction(fooVar)
  // Other stuff
}

func InnerFunction(f *FooIface) {
  f.FooFunc()
  // Other stuff
}

I'm able to easily test InnerFunction by creating a mock struct that implements FooIface with a stubbed FooFunc() so all is good here. However, what if I wanted to test OuterFunction()? Then how would I stub FooFunc() from there since the injected dependency is created in OuterFunction()?

Do I have to move the creation of the &Foo{} struct up one level out of OuterFunction() by creating it in main and then injecting it into OuterFunction()?

In other words, how would you test the function that creates and injects the dependency?

  • 写回答

2条回答 默认 最新

  • duanpin2034 2018-09-08 23:01
    关注

    Often when people talk about dependency injection, it's in the context of creating objects (or in Go's case structs).

    The canonical way to do this in Go is to use a New function such as object_name.New(...) or package_name.NewObjectName(...). These functions take in the objects dependencies and output an instance of the object.

    Above you are doing a lot of your code in static functions. Could it be inverted into objects that are created and have methods on them? This is sometimes called inversion of control.

    type Foo {
        bar Bar
        baz Baz
    }
    
    func NewFoo(bar Bar, baz Baz) *Foo {
        return &Foo{ bar: bar, baz: baz }
    }
    
    func (foo *Foo) X() {
        foo.bar.Y()
        foo.baz.Z()
    }
    

    This model could be extended to multiple levels so testing is easier.

    foo := NewFoo(
        NewBar(...),
        NewBaz(...),
    )
    

    Here is a post that might be helpful.

    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效