Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add inject function/struct ability to go test for mock #22245

Closed
dypublic opened this issue Oct 13, 2017 · 4 comments
Closed

Proposal: Add inject function/struct ability to go test for mock #22245

dypublic opened this issue Oct 13, 2017 · 4 comments

Comments

@dypublic
Copy link

dypublic commented Oct 13, 2017

When I use go test for unit test, I found it is hard (maybe no way) to mock a function or a struct object inside a struct.

---------------------------
//download.go
---------------------------
func get(url string) string {
    resp, err := http.Get(url)
    if err != nil { return "" }
    defer resp.Body.Close()

    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil { return "" }
    return string(contents)
}

func downloader() string {
    content := get(BASE_URL)
    res := processString(content)
    return res
}

I think we could give a more powerful ability to go test (xxx_test.go), that we can create a mock function or a mock struct, and inject it and replace original symbol at compile phase. So we have a more flexible way to write the codes, not worry about "hardwire" function or struct in codes. Otherwise, we need to interface everything, just for testing and mock the object.

--------------------------------------------
download_test.go
--------------------------------------------
//inject/mock get 
func get(url string) string {
    return string("hello world!")
}

func TestDownloader(t *testing.T){
    res := downloader()
    if res != "hello world!" {
       t.Error("fail")
    }
}

Sorry, I'm not a native speaker. Hope I explained my idea clearly.

@gopherbot gopherbot added this to the Proposal milestone Oct 13, 2017
@dypublic dypublic changed the title Proposal: Add inject ability for go test Proposal: Add inject function/struct ability to go test for mock Oct 13, 2017
@cznic
Copy link
Contributor

cznic commented Oct 13, 2017

Sounds like an xy problem. Please show some code illustrating the problem you want to solve. Point out what you need but cannot do. Thanks.

@dypublic
Copy link
Author

Yes. See this question in link. https://stackoverflow.com/questions/19167970/mock-functions-in-go.
The solutions in that page, are not straight. Need to introduce another thing, like a interface or intermediate variable.

@dypublic
Copy link
Author

dypublic commented Nov 9, 2017

I edit my proposal, hope it is easy to understand now.

@rsc
Copy link
Contributor

rsc commented Nov 13, 2017

The testing package is deliberately minimal and avoids magic code rewriting like this. For complex cases there is the gomock tool, although it is a bit heavy-weight to use. In this specific case, where you want to override code you wrote, you can add to it (in the real copy of the code):

var getHook func(string) string

func get(url string) string {
    if getHook != nil { return getHook(url) }
    ... real code
}

and then in your test you can have your specific test case set and restore getHook:

func Test(t *testing.T) {
    getHook = myGet
    defer func() { getHook = nil }()
    ... your test ...
}

@rsc rsc closed this as completed Nov 13, 2017
@golang golang locked and limited conversation to collaborators Nov 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants