How to test Go function containing log.Fatal()

后端 未结 8 2189
南笙
南笙 2020-12-09 08:10

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

相关标签:
8条回答
  • 2020-12-09 09:02

    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")
    }
    
    0 讨论(0)
  • 2020-12-09 09:02

    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.)

    0 讨论(0)
提交回复
热议问题