使用接口进行模拟以进行测试
Go mocking with interfaces for testing
我是 Go 的新手,我来自 OOP 语言。现在这个概念在 go of interfaces 和 类.
中似乎完全不同
我想知道在测试的情况下模拟将如何工作。我感到困惑的是是否可以将 struct
用作 类 以及下面的方法是否是您想要的?假设 DefaultArticlesRepository
用于真实数据而 MockArticlesRepository
用于模拟它。
type ArticlesRepository interface {
GetArticleSections() []ArticleSectionResponse
}
type DefaultArticlesRepository struct{}
type MockArticlesRepository struct{}
func (repository DefaultArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
}
}
func (repository MockArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
}
}
func ArticleSectionsProvider(v ArticlesRepository) ArticlesRepository {
return v
}
func TestFoo(t *testing.T) {
realProvider := ArticleSectionsProvider(DefaultArticlesRepository{})
mockProvider := ArticleSectionsProvider(MockArticlesRepository{})
assert.Equal(t, realProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
})
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
}
首先,我建议您使用https://github.com/vektra/mockery 来根据接口自动生成模拟结构。实现像你这样的模拟结构是可以的,但我认为如果你真的不需要该结构的非常特殊的行为,那只会浪费你的时间和精力。
其次,我们不需要像您在代码中那样测试模拟结构。
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
所以当我们使用 mock structs 时,假设 struct a 是 struct 的依赖b。例如:
type A interface {
DoTask() bool
}
type a struct {}
func (sa *a) DoTask() bool {
return true
}
type b struct {
a A
}
func (sb *b) DoSomething() bool {
//Do some logic
sb.a.DoTask();
//Do some logic
return true;
}
并且您想测试结构 b 的函数 DoSomething。当然,在这种情况下,您不关心也不想测试 struct a 的函数 DoTask。然后你只需简单地提供一个 struct a 的 mock 来构造 b 在测试中。这个 mock 还可以帮助您避免在测试 struct b[ 时处理与 struct a 相关的任何问题=42=]。
现在你的测试应该是这样的:
func (s *TestSuiteOfStructB) TestDoSomething_NoError() {
//Suppose that mockedOfA is a mock of struct a
instanceOfB := b{a: mockedOfA}
mockedOfA.On("DoTask").Return(true)
actualResult := instanceOfB.DoSomething()
s.Equal(true, actualResult)
}
最后,这只是一件小事但没看清楚你的责任ArticleSectionsProvider.
我是 Go 的新手,我来自 OOP 语言。现在这个概念在 go of interfaces 和 类.
中似乎完全不同我想知道在测试的情况下模拟将如何工作。我感到困惑的是是否可以将 struct
用作 类 以及下面的方法是否是您想要的?假设 DefaultArticlesRepository
用于真实数据而 MockArticlesRepository
用于模拟它。
type ArticlesRepository interface {
GetArticleSections() []ArticleSectionResponse
}
type DefaultArticlesRepository struct{}
type MockArticlesRepository struct{}
func (repository DefaultArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
}
}
func (repository MockArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
}
}
func ArticleSectionsProvider(v ArticlesRepository) ArticlesRepository {
return v
}
func TestFoo(t *testing.T) {
realProvider := ArticleSectionsProvider(DefaultArticlesRepository{})
mockProvider := ArticleSectionsProvider(MockArticlesRepository{})
assert.Equal(t, realProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
})
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
}
首先,我建议您使用https://github.com/vektra/mockery 来根据接口自动生成模拟结构。实现像你这样的模拟结构是可以的,但我认为如果你真的不需要该结构的非常特殊的行为,那只会浪费你的时间和精力。
其次,我们不需要像您在代码中那样测试模拟结构。
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
所以当我们使用 mock structs 时,假设 struct a 是 struct 的依赖b。例如:
type A interface {
DoTask() bool
}
type a struct {}
func (sa *a) DoTask() bool {
return true
}
type b struct {
a A
}
func (sb *b) DoSomething() bool {
//Do some logic
sb.a.DoTask();
//Do some logic
return true;
}
并且您想测试结构 b 的函数 DoSomething。当然,在这种情况下,您不关心也不想测试 struct a 的函数 DoTask。然后你只需简单地提供一个 struct a 的 mock 来构造 b 在测试中。这个 mock 还可以帮助您避免在测试 struct b[ 时处理与 struct a 相关的任何问题=42=]。 现在你的测试应该是这样的:
func (s *TestSuiteOfStructB) TestDoSomething_NoError() {
//Suppose that mockedOfA is a mock of struct a
instanceOfB := b{a: mockedOfA}
mockedOfA.On("DoTask").Return(true)
actualResult := instanceOfB.DoSomething()
s.Equal(true, actualResult)
}
最后,这只是一件小事但没看清楚你的责任ArticleSectionsProvider.