DATA-DOG / go-sqlmock

Sql mock driver for golang to test database interactions
Other
6.06k stars 408 forks source link

mock.ExpectQuery returning unfulfilled expectations #178

Closed thelebdev closed 4 years ago

thelebdev commented 5 years ago

I've got the following function to query a Database Table:

func getPosts() (err error) {
    rows, err := db.Query("SELECT title_id, subtitle_id from posts")
    if err != nil {
        fmt.Println(err.Error())
    }
    var posts []Post // Declared before this function

    defer rows.Close()
    for rows.Next() {
        var titleID int
        var subtitleID string

        err := rows.Scan(&titleID, &subtitleID)
        if err != nil {
            fmt.Println(err.Error())
        }
        posts = append(posts, Post{titleID: titleID, subtitleID: subtitleID})

        if err := rows.Err(); err != nil {
            fmt.Println(err.Error())
        }
    }
    return err
}

Printing the results above yields the desired output. Moving on to my Unit Test,

package main

import (
    "testing"

    "github.com/DATA-DOG/go-sqlmock"
)

func TestShouldGetPosts(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_id", "subtitle_id"}).
        AddRow(1, 1, "subtitle-1").
        AddRow(2, 2, "subtitle-2").
        AddRow(3, 3, "subtitle-3")

    mock.ExpectQuery("SELECT (.+) from posts").WillReturnRows(rows)

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("There were unfulfilled expectations: %s", err)
    }
    getPosts() // to call the function itself
}

The problem is, I always get the following output

FAIL: TestShouldGetPosts (0.00s)
    db_queries_test.go:24: There were unfulfilled expectations: there is a remaining expectation which was not matched: ExpectedQuery => expecting Query, QueryContext or QueryRow which:
          - matches sql: 'SELECT (.+) from posts'
          - is without arguments
          - should return rows:
            row 0 - [1 subtitle-1]
            row 1 - [2 subtitle-2]
            row 2 - [3 subtitle-3]
FAIL
exit status 1
FAIL

I've followed the examples to the best of my knowledge.

l3pp4rd commented 5 years ago

In the test you check if all expectations are matched, before calling getPosts

thelebdev commented 5 years ago

Can you please further explain or refer me to a part of the documentation where I missed what you just said?

l3pp4rd commented 5 years ago

Look at the tests in the sqlmock library

piclemx commented 5 years ago

@christopheelkhoury reverse the call to your function and the expectations

getPosts() // to call the function itself

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