狂欢依赖注入

时间:2018-10-29 14:25:33

标签: go dependency-injection revel

我希望我的狂欢控制器使用各种服务,这些服务我会在单元测试中模拟出来。我是新手。在C#中,我将使用依赖项注入来注入它们。有一种常见的方式来狂欢吗?

似乎我找到的最好方法是在控制器的Before()方法中初始化真实的服务(可能使用通过连线解决的方法),并在测试的Before()方法中设置模拟版本。还是有更好的方法?

2 个答案:

答案 0 :(得分:1)

我使用filter注入依赖项。

过滤器测试控制器是否实现了特定的接口并填充了正确的依赖关系。下面是插入与数据库相关的依赖关系的示例:

func DependencyFilter(c *revel.Controller, filterChain []revel.Filter) {
    if ctrl, ok := c.AppController.(DataServiceController); ok {
        ctrl.SetDataService(<your dependency>)
    }

    // Different dependencies could be injected here:
    //if ctrl, ok := c.AppController.(FooController); ok {
    //  ctrl.SetFooService(<your dependency>)
    //}

    // Call the next filter
    if len(filterChain) > 0 {
        filterChain[0](c, filterChain[1:])
    }
}

DataServiceController在哪里:

type DataServiceController interface {
    SetDataService(ds services.DataService)
}

我将过滤器作为倒数第二个条目插入了init.go

revel.Filters = []revel.Filter{
    revel.PanicFilter,             // Recover from panics and display an error page instead.
    // ...
    DependencyFilter,              // Add dependencies
    revel.ActionInvoker,           // Invoke the action.
}

我的大多数控制器都需要相同的依赖项,所以我有一个都嵌入的基本控制器:

type BaseController struct {
    *revel.Controller
    DataService services.DataService
}

func (c *BaseController) SetDataService(ds services.DataService) {
    c.DataService = ds
} 

所以我的具体控制器看起来像这样:

type Home struct {
    BaseController
}

func (c Home) Index() revel.Result {
    // ...
}

也许有更好的方法,但这是我的方法。

答案 1 :(得分:0)

实际上,GO有很多DI系统。我搜索了几种,尝试使用它们,最后选择了一些补丁以提供更多便利。用法很简单:

package dependency

import (
   "fmt"

   "github.com/lisitsky/inject"
)

func init() {
   inject.Provide(NewStringer)
}

type stringer struct{}

func (s stringer) String() string {
    return "Hello, World"
}

func NewStringer() fmt.Stringer {
    return stringer{}
}

从一侧接受依赖关系(main.go):

package main


import (
   "fmt"

   "github.com/lisitsky/inject"

   _ "github.com/lisitsky/inject/examples/simple/dependency"
)

var ( 
   str fmt.Stringer
)

func main() {
   inject.Construct(&str)
   fmt.Println("My Stringer is:", str)
}

它还支持延迟初始化:

func main() {
   // define variables to be constructed later
   inject.ConstructLater(&str)

   // define dependency providers
   inject.Provide(NewStringer)

   // finalize construction - all DI variables would be initialized at one call
   injector.FinishConstruct()

   fmt.Println("My Stringer is:", str)
}