1

I'm trying to mock a method written with sqlboiler but I'm having massive trouble building the mock-query. The model I'm trying to mock looks like this:

type Course struct {
ID int, Name string, Description null.String, EnrollKey string, ForumID int, 
CreatedAt null.Time, UpdatedAt null.Time, DeletedAt null.Time, 
R *courseR, L courseL
}

For simplicity I want to test the GetCourse-method

func (p *PublicController) GetCourse(id int) (*models.Course, error) {

    c, err := models.FindCourse(context.Background(), p.Database, id)
    if err != nil {
        return nil, err
    }
    return c, nil
}

with this test

func TestGetCourse(t *testing.T) {
    db, mock, err := sqlmock.New()
    if err != nil {
        t.Fatalf("an error '%s' was not expected", err)
    }

    oldDB := boil.GetDB()
    defer func() {
        db.Close()
        boil.SetDB(oldDB)
    }()
    boil.SetDB(db)

    ctrl := &PublicController{db}

    rows := sqlmock.NewRows([]string{"ID", "Name", "Description", "EnrollKey", "ForumID"}).AddRow(42, "Testkurs", "12345", 33)

    query := regexp.QuoteMeta("SELECT ID, Name, Description, EnrollKey, ForumID FROM courses WHERE ID = ?")
    //mockQuery := regexp.QuoteMeta("SELECT * FROM `courses` WHERE (`course AND (`courses`.deleted_at is null) LIMIT 1;")

    mock.ExpectQuery(query).WithArgs(42).WillReturnRows(rows)

    course, err := ctrl.GetCourse(42)
    assert.NotNil(t, course)
    assert.NoError(t, err)
}

But running this test only returns

Query: could not match actual sql: "select * from course where id=? and deleted_at is null" with expected regexp "SELECT ID, Name, Description, EnrollKey, ForumID FROM courses WHERE ID = ?" bind failed to execute query And I can't really find out how to construct it correctly. How do I correctly mock the sqlboiler-query for running unit tests?

UPDATE I managed to solve this by using different parameters in AddRow()

.AddRow(c.ID, c.Name, null.String{}, c.EnrollKey, c.ForumID)

and building the query differently

query := regexp.QuoteMeta("select * from `course` where `id`=? and `deleted_at` is null")

Now my issue is that in contrast to this method the others have a very large complexity in comparison with a large amount of complex queries (mainly insert-operations). From my understanding, sqlboiler-tests needs to mimic every single interaction made with the database.

How do I extract the necessary queries for the large amount of database interactions? I solved my problem by just using the "actual sql-query" instead of the previously used one but I'm afraid this procedure is the opposite of efficient testing.

Karparetzu
  • 11
  • 3
  • Using regexp to validate SQL creates fragile and not reliable tests. It is enough to test passed and returned parameters, transactions scope and use SQL mock to return data. To test SQL query, it is advisable to implement it as a dedicated function (without any business logic) and develop integration tests for that function. That of course will require SQL migrations being implemented. – Dmitry Harnitski Jun 03 '22 at 23:34

0 Answers0