Given this code
func doomed() {
os.Exit(1)
}
How do I properly test that calling this function will result in an exist using go test
? This needs to occur within a suite of tests, in other words the os.Exit()
call cannot impact the other tests and should be trapped.
You can't, you would have to use
exec.Command
and test the returned value.I don't think you can test the actual
os.Exit
without simulating testing from the outside (usingexec.Command
) process.That said, you might be able to accomplish your goal by creating an interface or function type and then use a noop implementation in your tests:
Go Playground
There's a presentation by Andrew Gerrand (one of the core members of the Go team) where he shows how to do it.
Given a function (in
main.go
)here's how you would test it (through
main_test.go
):What the code does is invoke
go test
again in a separate process throughexec.Command
, limiting execution to theTestCrasher
test (via the-test.run=TestCrasher
switch). It also passes in a flag via an environment variable (BE_CRASHER=1
) which the second invocation checks for and, if set, calls the system-under-test, returning immediately afterwards to prevent running into an infinite loop. Thus, we are being dropped back into our original call site and may now validate the actual exit code.Source: Slide 23 of Andrew's presentation. The second slide contains a link to the presentation's video as well. He talks about subprocess tests at 47:09
I do this by using bouk/monkey:
monkey is super-powerful when it comes to this sort of work, and for fault injection and other difficult tasks. It does come with some caveats.
Code for testing:
Testing code: