I have defined the following Cobra subcommand that I'd like to test the output for using testify:
var childCmd = &cobra.Command{
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
id := args[0]
conn := getConn()
c := newClient(conn)
out, err := c.getResult(cmd.Context(), id)
if err != nil {
return err
}
fmt.Printf(
"Name:\t%v %v\nCity:\t%v\n",
out.GetFirstName().String(),
out.GetLastName().String(),
out.GetCity().String(),
)
return nil
},
}
func init() {
rootCmd.AddCommand(childCmd)
}
I can test the actual output with something like this:
func executeCommand(root *cobra.Command, args ...string) (output string, err error) {
buf := new(bytes.Buffer)
root.SetOut(buf)
root.SetErr(buf)
root.SetArgs(args)
err = root.Execute()
if err != nil {
fmt.Println(err)
}
return buf.String(), err
}
func TestGetResult(t *testing.T) {
rootCmd.AddCommand(childCmd)
output, _ := executeCommand(rootCmd, "child", "1")
assert.Equal(t, "test", output)
}
But what I'm missing is how to mock the gRPC client and the its respective call to getResult
.
Is there a better way to create a new gRPC client than within the RunE
func that would help facilitate mocking? As of right now, the unit test attempts to connect to a non-existent gRPC client and fails.
One option is to run the gRPC server within the unit test using a random port and have the client connect to that. This is possible if you have the gRPC server in your tree as well, and if it will not bring in other things you cannot mock.
The easier option is to extract the gRPC initialization to a function variable, and set it to return a mock during the unit test: