DATA-DOG / go-sqlmock

Sql mock driver for golang to test database interactions
Other
6.02k stars 406 forks source link

Getting length of sqlmock.Rows #256

Closed niklod closed 2 months ago

niklod commented 3 years ago

Hello! I think it would be great to make a method Len() for sqlmock.Rows. It will be useful for cases, where we comparing length of resulting rows and mocked rows.

Example:

func Test_GetById_OneRow(t *testing.T) {
    db, mock, err := sqlmock.New()
    repo := NewRepository(db)

    rows := sqlmock.NewRows([]string{"test1", "test2"})
    rows.AddRow("test", "test")

    mock.ExpectQuery("SELECT id").WillReturnRows(rows)

    res, err := repo.PostsByUserId(userId)

    assert.Equal(t, len(res), rows.Len())
    assert.NilError(t, err)
}

Currently we have to manually enter the length of the mocked rows like this:

func Test_GetById_OneRow(t *testing.T) {
    db, mock, err := sqlmock.New()
    repo := NewRepository(db)

    rows := sqlmock.NewRows([]string{"test1", "test2"})
    rows.AddRow("test", "test")

    mock.ExpectQuery("SELECT id").WillReturnRows(rows)

    res, err := repo.PostsByUserId(userId)

    assert.Equal(t, len(res), 1)
    assert.NilError(t, err)
}

During the development process, tests can be changed and we should manually change this length. Will glad to contribute if you think this is a good idea.

diegommm commented 2 months ago

Hi @niklod! Thank you for your detailed submission. However, I think that if you have to manually write every line with rows.AddRow it would also be fair to ask that you manually enter the number of lines you wrote. Nonetheless, you still have ways to keep the number of rows you entered in your test at hand with sqlmock, and that could be done by using the (*Rows).AddRows method. Example:

// test setup
db, mock, err := sqlmock.New()
require.NoError(t , err)
colNames := []string{"id", "enabled", "name"}
rowsData := [][]driver.Value{
    {1, true, "someone"},
    {2, false, "another person"},
}
// other stuff, like your repository

// setup expectations
rows := mock.NewRows(colNames).AddRows(rowsData...)
mock.ExpectQuery(`SELECT id, enabled, name from users WHERE admin = ?`).WillReturnRows(rows)

// execute and assert
// ... use `db` to get a `results` slice using your repository
assert.Len(t, myResult, len(rowsData))

Also note that you're using sqlmock.NewRows instead of your sqlmock.Sqlmock's NewRows method, which I fixed in the example (read the documentation for more information about this). I think this way you can achieve your goal.

Thank you!