How to test os.exit scenarios in Go

后端 未结 5 1822
渐次进展
渐次进展 2020-12-23 12:09

Given this code

func doomed() {
  os.Exit(1)
}

How do I properly test that calling this function will result in an exit using go test

5条回答
  •  生来不讨喜
    2020-12-23 12:14

    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)

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func Crasher() {
        fmt.Println("Going down in flames!")
        os.Exit(1)
    }
    

    here's how you would test it (through main_test.go):

    package main
    
    import (
        "os"
        "os/exec"
        "testing"
    )
    
    func TestCrasher(t *testing.T) {
        if os.Getenv("BE_CRASHER") == "1" {
            Crasher()
            return
        }
        cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
        cmd.Env = append(os.Environ(), "BE_CRASHER=1")
        err := cmd.Run()
        if e, ok := err.(*exec.ExitError); ok && !e.Success() {
            return
        }
        t.Fatalf("process ran with err %v, want exit status 1", err)
    }
    

    What the code does is invoke go test again in a separate process through exec.Command, limiting execution to the TestCrasher 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

提交回复
热议问题