Reputation: 6185
I have a cli tool written in Go which produces the following output:
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
I would like to verify this output within a test.
The test I have written (and doesn't pass) is as follows:
package command
import (
"testing"
"github.com/my/package/foo"
)
type FakeCliContext struct{}
func (s FakeCliContext) String(name string) string {
return "foobar"
}
func ExampleInvalidComponentReturnsError() {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(foo.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
// Output:
// Command: config get
// Env: int
// Component: foo-component
//
// Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
}
The majority of the code is creating fake objects that I'm injecting into my function call GetConfig
.
Effectively there is no return value from GetConfig
only a side effect of text being printed to stdout.
So I'm using the Example<NameOfTest>
format to try and verify the output.
But all I just back when I run go test -v
is:
=== RUN ExampleInvalidComponentReturnsError
exit status 1
FAIL github.com/my/package/thing 0.418s
Does anyone know what I might be missing?
I've found that if I add an additional test after the 'Example' one above, for example called Test<NameOfTest>
(but consistenting of effectively the same code), then this will actually display the function's output into my stdout when running the test:
func TestInvalidComponentReturnsError(t *testing.T) {
fakeBaseURL := "http://api.foo.com"
fakeCliContext := &FakeCliContext{}
fakeFetchFlag := func(utils.CliContext) (map[string]string, error) {
return map[string]string{
"env": "int",
"component": "foo-component",
}, nil
}
GetConfig(*fakeCliContext, fakeFetchFlag, fakeBaseURL)
}
The above example test will now show the following output when executing go test -v
:
=== RUN TestInvalidComponentReturnsError
Command: config get
Env: int
Component: foo-component
Unable to find any configuration within Cosmos (http://api.foo.com) for foo-component.
exit status 1
FAIL github.com/bbc/apollo/command 0.938s
Upvotes: 0
Views: 360
Reputation: 6185
OK so the solution to this problem was part architecture and part removal/refactor of code.
I extracted the private functions from the cli command package so they became public functions in a separate function
I refactored the code so that all dependencies were injected, this then allowed me to mock these objects and verify the the expected methods were called
Now the private functions are in a package and made public, I'm able to test those things specifically, outside of the cli context
Finally, I removed the use of os.Exit as that was a nightmare to deal with and wasn't really necessary
Upvotes: 0