Search code examples
goglide-golang

Mocking functions called from within another in golang


I am trying to stub os.Stat and ioutil.ReadFile(path) as used the code below or if you like here on go playground [1]

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strings"
)

func AssignFileValueFrom(path string, val *string) {
    var (
        tempValue []byte
        err       error
    )

    if _, err = os.Stat(path); err == nil {
        if err != nil {
            fmt.Println("There was a os stat error:", err)
        }

        tempValue, err = ioutil.ReadFile(path)
        if err != nil {
            fmt.Println("There was an io read error:", err)
        }
        *val = strings.TrimSpace(string(tempValue))
    }
}

I have used testify and tried following the example here [2]

package main

import (
    "testing"

    "github.com/stretchr/testify/mock"
)

type osMock struct {
    mock.Mock
}

func (o osMock) Stat(path string) (interface{}, error) {
    return nil, nil
}

func TestAssignFileValueFrom(t *testing.T) {
    var test string
    osm := new(osMock)
    osm.On(`Stat`, `./.test`).Return([]byte(`1`), nil)

    AssignFileValueFrom(`./.test`, &test)
    // assert.Equal(t, `1`, test)
    osm.AssertExpectations(t)
}

What am I not doing correctly??

[1] https://play.golang.org/p/xcbdMkMwoBN

[2] https://github.com/stretchr/testify#mock-package


Solution

  • Your code with osMock doesn't any how influence execution of AssignFileValueFrom function. There is a direct call of os.Stat and it won't be substituted just because you have declared osMock somewhere.
    To do actual testing you should use interfaces and dependency injection to be able to test your code.
    First of all os.Stat call must be substituted with call to your struct that implements an interface with same method defined. And you need to create at least 2 implementations of this interface: 1 - is actual working code to use, 2 - mock as your osMock struct to use in test. And you need to inject it or pass it to AssignFileValueFrom and then use to call Stat method on it.