简体   繁体   English

Go mocking 带测试接口

[英]Go mocking with interfaces for testing

I'm pretty new with Go, and I'm coming from OOP languages.我对 Go 很陌生,而且我来自 OOP 语言。 Now the concept seems quite different in go of interfaces and classes.现在这个概念在接口和类的 go 中似乎完全不同。

I was wondering how mocking would work in case of testing.我想知道 mocking 在测试的情况下如何工作。 The confusion I'm having is whether ok to use struct as a classes and if the approach below is how you suppose to do?我遇到的困惑是是否可以将struct用作类,如果下面的方法是你想怎么做的? Assuming that DefaultArticlesRepository would be for real data and MockArticlesRepository for mocking it.假设DefaultArticlesRepository用于真实数据,而MockArticlesRepository用于 mocking 它。

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",
        },
    })
}

Firstly, I suggest you to use https://github.com/vektra/mockery for generating mock structs automatically based on interfaces.首先,我建议你使用https://github.com/vektra/mockery来根据接口自动生成模拟结构。 Implementing a mock struct like your is ok but I think it just wastes your time and effort if you do not really need a very special behavior for that struct.实现一个像你这样的模拟结构是可以的,但我认为如果你真的不需要该结构的非常特殊的行为,那只会浪费你的时间和精力。

Secondly, we do not need to test mock structs like you do in your code.其次,我们不需要像您在代码中那样测试模拟结构。

assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
    {
        Title: "Mock response",
        Tag:   "Mock Tag",
    },
})

So when we use mock structs, suppose struct a is a dependency of struct b .因此,当我们使用模拟结构时,假设 struct a是 struct b的依赖项。 For example:例如:

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;
}

And you want to test function DoSomething of struct b .并且您想测试 struct b的 function DoSomething 。 Of course you do not care and do not want to test function DoTask of struct a in this case.当然,在这种情况下,您不关心也不想测试结构a的 function DoTask。 Then you just simply provide a mock of struct a to struct b in the test.然后,您只需在测试中提供 struct a到 struct b的模拟。 This mock also helps you avoid to deal with any struggle related to struct a in testing struct b .这个模拟还可以帮助您避免在测试 struct b时处理与 struct a相关的任何问题。 Now your test should be like this:现在你的测试应该是这样的:

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

The last, this is just a small thing but do not see a clear responsibility of your ArticleSectionsProvider .最后,这只是一件小事,但看不到您的ArticleSectionsProvider的明确责任。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM