Инъекция зависимости от пирушки - PullRequest
0 голосов
/ 29 октября 2018

Я надеюсь, что мои контроллеры пирушек используют различные сервисы, которые я макетирую для модульных тестов. Я новичок в Go; в C # я бы внедрил их, используя внедрение зависимостей. Есть ли общий способ сделать это в пирушке?

Похоже, что лучший способ, который я нашел, - это инициализировать реальные сервисы в методе Before () контроллера (возможно, с помощью метода, решаемого по проводам) и установить фиктивные версии в методе Before () теста. , Или есть лучший способ?

Ответы [ 2 ]

0 голосов
/ 24 марта 2019

Я использую фильтр для внедрения зависимостей.

Фильтр проверяет, реализует ли контроллер определенные интерфейсы и вставляет ли правильную зависимость. Вот пример, который вставляет связанную с базой данных зависимость:

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 {
    // ...
}

Возможно, есть лучшие пути, но это мой подход.

0 голосов
/ 01 ноября 2018

На самом деле есть много систем DI для GO. Я искал несколько, пытался использовать и, наконец, выбрал один с некоторыми исправлениями для большего удобства. Использование довольно просто:

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)
}
...