Go中的模拟接收器功能

I'm trying to unit test a receiver function that calls other receiver functions in that struct.

Let's say I want to test Three() and mock the call to two() in the following:

type MyStruct struct {
    a string
    b string
}

func (m *MyStruct) one() int {
    return 2
}

func (m *MyStruct) two() int {
    return m.one() * 2
}

func (m *MyStruct) Three() int {
    return m.two() * 2
}

I was following method two of the following answer.

I created a custom constructor for every single function that I wanted to unit test and overrode those methods with mocked versions. But I thought it may not be easy to maintain the code once the number of functions grow.

Is there any preferred way of mocking such functions? I wish the official documentation had some guidelines on how to mock things in different scenarios, similar to what mox on Python provides.

Also, note that I don't want to use a third party mocking library.

That is a really un-idiomatic way to test your stuff. All this mocking might be needed in other languages, but please don't do it in Go.

The natural way to test your code in the example you gave would be: 1) Write a table driven test for MyStruct.one and make sure you test all cases. Now that you know one works perfectly fine 2) do the same with MyStruct.two. Note that testing unexported stuff is possible, useful and common in Go. Now there is no longer a need need to mock some methods, just 3) write some table driven test for MyStruct.Three and check it works.

But maybe your methods one and two do fancier stuff, and access the environment (filesystem, database, network) and you do not want your tests of Three to depend on that? So refactor your code! Maybe Three should not be a method of MyStruct but a function which takes an interface OneAndTwoer as an argument and your production code calls Three with "real" MyStructs while your testcode calls it with InMemoryMyStrcuts which do not depend on the environment? You could call it a mock, I'd call it a different implementation of an interface.

In your example it is simple to give advice: Use table driven tests for one, two and Three and do not mock. For a more realistic problem the advice might be different but it is hard to give a general advice without knowing the circumstances. Best general advice is: Take a look at the test in the standard library where you'll find useful patterns for almost every testing scenario.