Say, I had the following code that prints some log messages. How would I go about testing that the correct messages have been logged? As log.Fatal
calls o
There used to be an answer here that I referred to, looks like it got deleted. It was the only one I've seen where you could have passing tests without modifying dependencies or otherwise touching the code that should Fatal.
I agree with other answers that this is usually an inappropriate test. Usually you should rewrite the code under test to return an error, test the error is returned as expected, and Fatal at a higher level scope after observing the non-nil error.
To OP's question of testing that the that the correct messages have been logged, you would inspect inner process's cmd.Stdout
.
https://play.golang.org/p/J8aiO9_NoYS
func TestFooFatals(t *testing.T) {
fmt.Println("TestFooFatals")
outer := os.Getenv("FATAL_TESTING") == ""
if outer {
fmt.Println("Outer process: Spawning inner `go test` process, looking for failure from fatal")
cmd := exec.Command(os.Args[0], "-test.run=TestFooFatals")
cmd.Env = append(os.Environ(), "FATAL_TESTING=1")
// cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
err := cmd.Run()
fmt.Printf("Outer process: Inner process returned %v\n", err)
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
// fmt.Println("Success: inner process returned 1, passing test")
return
}
t.Fatalf("Failure: inner function returned %v, want exit status 1", err)
} else {
// We're in the spawned process.
// Do something that should fatal so this test fails.
foo()
}
}
// should fatal every time
func foo() {
log.Printf("oh my goodness, i see %q\n", os.Getenv("FATAL_TESTING"))
// log.Fatal("oh my gosh")
}
You cannot and you should not. This "you must 'test' each and every line"-attitude is strange, especially for terminal conditions and that's what log.Fatal is for. (Or just test it from the outside.)