I have two Go test cases as shown below that test a gRPC function called MyEndpoint.
MyEndpoint is supposed to succeed when the database row it selects has Field1 == "A" and return an error otherwise.
I'm mocking out the database with the go-sqlmock package from Data-dog.
package mypackage_test
import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/require"
)
type MyEntity struct {
Id sql.NullInt32 `db:"id"`
Field1 sql.NullString `db:"field1"`
Field2 sql.NullString `db:"field2"`
Field3 sql.NullString `db:"field3"`
}
var Columns = []string{
"id",
"field_1",
"field_2",
"field_3"
}
var dbRow = []driver.Value{int32(999), "A", "B", "C"]
func TestMyTestA(t *testing.T) {
t.Run("Verify MyEndpoint Fails when mocked Database row has Field1 != A", func(t *testing.T) {
api, err := getMyAPI()
require.Nil(t, err)
defer api.Close()
api.DBMock.ExpectBegin()
api.DBMock.MatchExpectationsInOrder(false)
modifiedDBRow := dbRow
modifiedDBRow[0] = "Z"
api.DBMock.ExpectQuery("SELECT").
WithArgs(int32(999)).WillReturnRows(sqlmock.NewRows(Columns).AddRow(modifiedDBRow...))
api.DBMock.ExpectCommit()
_, err = ... // Call MyEndpoint with parameter Id: int32(999)
api.DBMock.ExpectClose()
require.NotNil(t, err)
})
}
func TestMyTestB(t *testing.T) {
t.Run("Verify MyEndpoint succeeds when mocked Database row has Field1 == A", func(t *testing.T) {
api, err := getMyAPI()
require.Nil(t, err)
defer api.Close()
api.DBMock.ExpectBegin()
api.DBMock.MatchExpectationsInOrder(false)
api.DBMock.ExpectQuery("SELECT").
WithArgs(int32(999)).WillReturnRows(sqlmock.NewRows(Columns).AddRow(dbRow...))
api.DBMock.ExpectCommit()
_, err = ... // Call MyEndpoint with parameter Id: int32(999)
api.DBMock.ExpectClose()
require.Nil(t, err)
})
}
When I run these two test cases individually, they both pass.
But when I run them together, TestMyTestB fails because it thinks Field1 == "Z".
So clearly TestMyTestA is interfering with TestMyTestB. Why?
It seems that the mocking done in TestMyTestA case is still in effect when it gets to TestMyTestB and the mocking I'm doing in TestMyTestB case is completely ignored.
How can I mock these two test cases out independently of one another?
It's because of an incorrect assignment to
modifiedDBRowslice in your first test. Remember that a slice does not store any data, it just describes a section of an underlying array.So when you modified
modifiedDBRowin the first test, you've inherently modified the underlying array containing value at[0], fromAtoZ, which persists when you read thedbRowin your next test. Either reset the value at the end of the first test or have a different set of variables to use across tests.