Mock.On panics when it expects a `func` parameter
Hello, I've been having issues mocking an interface that expects a func as a parameter. Not sure if this is a bug or maybe an opportunity to improve a little bit the docs (And if this is not the place for this, I'm really really sorry. I hope you can redirect me to the right place to ask these questions)
My interface:
type ExcelFileReader interface {
ForEachRow(
fileAbsolutePath string,
sheetName string,
closure func(row []string) (bool, error), // Here it's where the issue starts
) error
}
My implementation:
type FileParser struct {
reader file.ExcelFileReader
}
func (fp FileParser) GetDataPoints(
path string,
df DataFile,
) (data []model.DataPoint, err error) {
if path == "" {
return data, fmt.Errorf("path cannot be empty")
}
if df.IsZero() {
return data, fmt.Errorf("data file cannot be empty")
}
fpath := filepath.Join(path, df.Filename())
err = fp.reader.ForEachRow(fpath, df.SheetName(), func(row []string) (bool, error) {
dp, dpErr := parseDataPoint(row)
if dpErr != nil {
return false, dpErr
}
data = append(data, dp)
return true, nil
})
return data, err
}
My mock:
type MockExcelFileReader struct {
Mock mock.Mock
}
func (m MockExcelFileReader) ForEachRow(
fileAbsolutePath string,
sheetName string,
closure func(row []string) (bool, error),
) error {
args := m.Mock.Called(
fileAbsolutePath,
sheetName,
closure,
)
return args.Error(0)
}
And inside my test, I have a helper function to create an instance of the mock:
func getTestExcelFileReader(
testPath string,
testDataFile DataFile,
err error,
) mocks.MockExcelFileReader {
tr := mocks.MockExcelFileReader{}
tr.Mock.On(
"ForEachRow",
fmt.Sprintf("%s/%s", testPath, testDataFile.Filename()),
testDataFile.SheetName(),
mock.AnythingOfType("func(row []string) (bool, error)"),
).Return(err)
return tr
}
And when I run the test, what I get is:
panic:
mock: Unexpected Method Call
-----------------------------
ForEachRow(string,string,func([]string) (bool, error))
0: "some path/some filename"
1: "some sheet name"
2: (func([]string) (bool, error))(0x57b640)
The closest call I have is:
ForEachRow(string,string,mock.AnythingOfTypeArgument)
0: "some path/some filename"
1: "some sheet name"
2: "func(row []string) (bool, error)"
Diff: 0: PASS: (string=some path/some filename) == (string=some path/some filename)
1: PASS: (string=some sheet name) == (string=some sheet name)
2: FAIL: type func(row []string) (bool, error) != type - (func([]string) (bool, error)=0x57b640) [recovered]
My guess is there's a problem when I'm using mock.AnythingOfType("func(row []string) (bool, error)") inside the Mock.On method. And of course, I can't pass an actual func since by doing this, I'll get an exception:
panic: cannot use Func in expectations. Use mock.AnythingOfType("func([]string) (bool, error)")
Please let me know if more info is needed. If there's a problem on how I'm using the mock, then I'd like understand and maybe contribute with a tiny PR adding an example to the docs. I think this could help a few folks. I did some research on line and I found people asks these questions but no clear answer is found
The error message you got suggests this is a known limitation and shows you what you need to do:
panic: cannot use Func in expectations. Use
mock.AnythingOfType("func([]string) (bool, error)")
This limitation is unlikely to be addressed as functions cannot be compared in Go, even using reflection.