Mocking the exec.Command
interface in Golang is an absolute pain. You run the risk of running system commands in a unit test context or are required to build out a custom solution to run your commands in an isolated and safe manner which still isn't ideal. Enter mockcmd
, the easy and safe way to mock your exec.Command
functions.
mockcmd
accomplishes a safe and easy mocking of the exec.Command
interface by creating a fake cmd
function and passing your command and args through to it. We assert that the Stdout
gets passed through and returned correctly for success and that an err
gets returned in the case of failure.
go get github.com/Justintime50/mockcmd
Below is an example on how to setup your CMD command in a way it can be easily mocked:
package mypackage
import (
"github.com/Justintime50/mockcmd/mockcmd"
)
// Pass in `exec.Command` as the context for your real command
func main() {
out, _ := myCommandFunction(exec.Command)
fmt.Println(out.String())
}
func myCommandFunction(cmdContext mockcmd.ExecContext) (*bytes.Buffer, error) {
cmd := cmdContext("echo", "Hello World")
var outb bytes.Buffer
cmd.Stdout = &outb
err := cmd.Run()
if err != nil {
fmt.Printf("Failed to run command: %s", err)
return nil, err
}
return &outb, nil
}
Below is an example on how to setup your test to mock your command from above:
// Mock a success and failure response from exec.Command
func TestMyCommandFunctionSuccess(t *testing.T) {
stdout, err := myCommandFunction(mockcmd.MockExecSuccess)
mockcmd.Success(t, stdout, err)
}
func TestMyCommandFunctionFailure(t *testing.T) {
_, err := myCommandFunction(mockcmd.MockExecFailure)
mockcmd.Fail(t, err)
}
// The following functions are required in each package that will mock an exec.Command
// Do not alter the following when placed into your package_test.go file
func TestMockProcessSuccess(t *testing.T) {
if os.Getenv("GO_TEST_PROCESS") != "1" {
return
}
os.Stdout.WriteString("mocked Stdout")
os.Exit(0)
}
func TestMockProcessFailure(t *testing.T) {
if os.Getenv("GO_TEST_PROCESS") != "1" {
return
}
os.Exit(1)
}
# Get a comprehensive list of development tools
make help
- Inspired by the articles by Jamie Thompson and Nate Finch