spf13 / cobra

A Commander for modern Go CLI interactions
https://cobra.dev
Apache License 2.0
38.41k stars 2.86k forks source link

SetOut not working #2187

Closed jeremyhahn closed 2 months ago

jeremyhahn commented 2 months ago

I have a unit test that follows the example shown here.

It's not working. The output goes to stdout and not my bytes buffer. I don't see where c.outWriter is ever populated in the calls to Execute*. The only place I see it being populated is the UsageString method.

What is the best practice for unit testing Cobra CLIs?

jeremyhahn commented 2 months ago

After stepping through a debugger, I was able to figure out how to get it working. Following up with the solution in case it helps someone else.

I think it would be nice if it worked using only the call to SetOut / SetErr. Only mentioning this as I noticed you're soliciting input for Cobra v2 :) Thanks for a great lib!

var helloCmd = &cobra.Command{
    Use:   "hello [name]",
    Short: "Prints hello",
    Long:  `Example command to test capturing output for test assertions`,
    Args:  cobra.MinimumNArgs(1),
    Run: func(cmd *cobra.Command, args []string) {

        fmt.Printf("Hello, %s", args[0])
    },
}

var helloCmd2 = &cobra.Command{
    Use:   "hello [name]",
    Short: "Prints hello",
    Long:  `Example command to test capturing output for test assertions`,
    Args:  cobra.MinimumNArgs(1),
    Run: func(cmd *cobra.Command, args []string) {

        cmd.Printf("Hello, %s", args[0])
    },
}

// Fails when output is written using stdlib
// print statement
func TestHello(t *testing.T) {

    b := new(bytes.Buffer)

    helloCmd.SetOut(b)
    helloCmd.SetErr(b)
    helloCmd.SetArgs([]string{"world"})

    err := helloCmd.Execute()
    assert.Nil(t, err)
    assert.Equal(t, "Hello, world", string(b.Bytes()))
}

// Works when writing to the Print* methods
// that belong to the *cobra.Command instance
// passed into the command's Run method.
func TestHello2(t *testing.T) {

    b := new(bytes.Buffer)

    helloCmd2.SetOut(b)
    helloCmd2.SetErr(b)
    helloCmd2.SetArgs([]string{"world"})

    err := helloCmd2.Execute()
    assert.Nil(t, err)
    assert.Equal(t, "Hello, world", string(b.Bytes()))
}