How to unit test os/exec's cmd.Start() in golang?

Issue

I’m trying to mock cmd.Start() in Unit test and could not able figure out

Do we need to mock the entire function or can we mock cmd.Start() function?

Can someone help me in this?

    package main
    
    import (
        "bytes"
        "fmt"
        "os/exec"
    )
    
    var execCommand = exec.Command
    func main() {
        stdout := &bytes.Buffer{}
        cmd := execCommand("cmd")
        syscall.SysProcAttr := &syscall.SysProcAttr{CmdLine: "/S /c C:\\Temp\\test.exe /S C:\\Temp\\test.log"}
        cmd.Stdout = stdout
    
        errs := cmd.Start()
        if errs != nil {
            fmt.Println("command run fialed :", errs)
            fmt.Println("OUTPUT :", stdout.String())
        }
    
    }

Unit Test:

func fakeExecCommand(command string, args ...string) *exec.Cmd {
    cs := []string{"-test.run=TestExecCommandHelper", "--", command}
    cs = append(cs, args...)
    cmd := exec.Command(os.Args[0], cs...)
    es := strconv.Itoa(mockedExitStatus)
    cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1", "STDOUT=" + mockedStdout, "EXIT_STATUS=" + es}
    return cmd
}

Solution

I was not able to mock cmd.Start(), we cannot do that anyway and below is the way which worked for me.

    func fakeExecCommand(command string, args ...string) *exec.Cmd {
            cs := []string{"-test.run=TestExecCommandHelper", "--", "ENTER YOUR COMMAND HERE"}
            cs = append(cs, args...)
            cmd := exec.Command(os.Args[0], cs...)
            es := strconv.Itoa(mockedExitStatus)
            cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1", "STDOUT=" + mockedStdout, "EXIT_STATUS=" + es}
            return cmd
        }
    
    
    
        func TestPrintDate(t *testing.T) {
            mockedExitStatus = 1
            mockedStdout = "Sun Aug 201"
            execCommand = fakeExecCommand
            defer func() { execCommand = exec.Command }()
            expDate := "Sun Aug 20"
        
            out, _ := printDate()
            if string(out) != expDate {
                t.Errorf("Expected %q, got %q", expDate, string(out))
            }
        }

/////////CODE///////

    func printDate() ([]byte, error) {
        cmd := execCommand("date")
        out, err := cmd.CombinedOutput()
        return out, err
    }

Referred below link :

How to mock exec.Command for multiple unit tests in Go lang?

Answered By – meena sushanth

Answer Checked By – Clifford M. (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.