Search code examples
unit-testinggogo-sqlmock

Why "mock.ExpectQuery" return "is without arguments"


Below is my unit test file:

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

    if err != nil {
        t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
    }

    defer db.Close()

    rows := sqlmock.NewRows([]string{"id", "title", "body"}).
        AddRow(1, "post 1", "hello").
        AddRow(2, "post 2", "world")

    mock.ExpectQuery("SELECT (.+) FROM testmock").
        WillReturnRows(rows)

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expectations: %s", err)
    }

}

enter image description here

enter image description here

framework:gin

database: gorm

I want to write a unit test..

I have two questions:

  1. How sqlmock.New() choose the database?
  2. Why mock.ExpectQuery return is without argument

Thanks in advance.


Solution

    1. How sqlmock.New() choose the database?

    Answer: It does not make an actual call to database. Its a Mock which means not real Database.

    1. Why mock.ExpectQuery return is without argument

    Answer: I don't see a call to AddLike() inside TestAddLike(t *testing.T). Try putting that as well:

    func TestAddLike(t *testing.T) {
        db, mock, err := sqlmock.New()
    
        if err != nil {
            t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
        }
    
        defer db.Close()
    
        rows := sqlmock.NewRows([]string{"id", "title", "body"}).
            AddRow(1, "post 1", "hello").
            AddRow(2, "post 2", "world")
    
        mock.ExpectQuery("SELECT (.+) FROM testmock").
            WillReturnRows(rows)
     
        AddLike() // <- Add the call to actual function here. Before mock.ExpectationsWereMet
    
        if err := mock.ExpectationsWereMet(); err != nil {
            t.Errorf("there were unfulfilled expectations: %s", err)
        }
    
    }
    
    1. I want to check my database whether it has increased

    Answer: You must not. The main intention of writing a unit test is to isolate (independent of actual Database calls or API calls to some server) the function and test the logic of function based on output of those dependencies (eg: DB throws an error or the API call returns different response). Calling actual DB will break that rule. That is where the integration tests come into action.

    Now, as a part of unit test , you only check:

    • if the correct SQL query is passed to SQL mock
    • Once you return the mock response of the DB, verify that the output of the function is as expected