Тестирование и насмешка над функцией, которая не возвращает никакого значения
Я хочу протестировать функцию, которая не возвращает никакого значения, а вместо этого запускает другие функции. Читая о тестировании, я нашел информацию о том, что это называется поведенческой проверкой, и что с помощью насмешек я могу проверить, какие функции и в каком порядке срабатывают. Однако у меня есть проблема с реализацией правильной техники для моего кода.
Давайте рассмотрим простой пример следующего интерфейса и структуры (этот пример очень прост для упрощения объяснения):
type ExampleInterface interface {
DoSomething(arg int)
DoEvenMore(arg int)
AndEvenMore(arg int)
}
type ExampleStruct struct {
Id string
// Other fields
}
func (e *ExampleStruct) DoSomething(arg int) {
arg2 := arg * 2
e.DoEvenMore(arg2)
arg3 := arg * 3
e.AndEvenMore(arg3)
}
func (e *ExampleStruct) DoEvenMore(arg int){
fmt.Println("I did so many operations here using ", arg)
}
func (e *ExampleStruct) AndEvenMore(arg int) {
// Performing other operations on arg
}
Теперь я хочу проверить функцию DoSomething
, Поскольку он не возвращает никакого значения, я хочу проверить, происходит ли после вызова этой функции с аргументом 3 следующая цепочка событий: функция DoEvenMore
вызывается один раз с аргументом 6
и следующая функция AndEvenMore
вызывается один раз с аргументом 9
Я написал следующий тест:
func TestDoSomething(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockClient := mocks.NewMockExampleInterface(mockCtrl)
example := ExampleStruct("ExampleId")
gomock.InOrder(
mockClient.EXPECT().DoSomething(3).Return().Times(1)
mockClient.EXPECT().DoEvenMore(6).Return().Times(1)
mockClient.EXPECT().AndEvenMore(9).Return().Times(1)
)
example.DoSomething(3)
}
Однако, когда я запускаю этот тест, я получаю ошибку: Unexpected call to *mocks.MockExampleInterface.DoSomething(..)
,
Как мне правильно выполнить насмешку в таком примере?
1 ответ
Два метода, вызываемые DoSomething
являются конкретными реализациями, вы не можете издеваться над чем-то подобным в Go.
Чтобы достичь того, что вы хотите DoSomething
будет зависеть от интерфейса, который определяет эти два метода и вызывает их вместо конкретных.
type DoMorer interface {
DoEvenMore(arg int)
AndEvenMore(arg int)
}
type ExampleStruct struct {
Id string
// Other fields
}
func (e *ExampleStruct) DoSomething(arg int, dm DoMorer) {
arg2 := arg * 2
dm.DoEvenMore(arg2)
arg3 := arg * 3
dm.AndEvenMore(arg3)
}
При такой настройке во время тестирования вы можете создать макет для DoMorer
интерфейс и передать это DoSomething
,
DoMorer
не нужно передавать в качестве аргумента, это может быть поле ExampleStruct
или глобальный, все, что соответствует вашим потребностям.