Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expectations are not met #29

Closed
mantzas opened this issue Feb 3, 2016 · 11 comments
Closed

Expectations are not met #29

mantzas opened this issue Feb 3, 2016 · 11 comments

Comments

@mantzas
Copy link

mantzas commented Feb 3, 2016

Hi,

i am mocking a insert statement but the expectation fails, event though i cannot see why.
The following error message reveal that the arguments are identical.

sql_writer_test.go:29: error was not expected while writing event: exec query 'INSERT INTO Event (SourceId, Created, EventType, Version, Payload) VALUES (?, ?, ?, ?, ?)', args [2eb5880e-4bfd-4450-92fc-df851bae5dbb 2016-02-03 22:05:00.712109 +0000 UTC TEST 1 {"version":1,"name":"Joe","balance":12.99,"birth_date":"2015-12-13T23:59:59+02:00"}] does not match expected [2eb5880e-4bfd-4450-92fc-df851bae5dbb 2016-02-03 22:05:00.712109 +0000 UTC TEST 1 {"version":1,"name":"Joe","balance":12.99,"birth_date":"2015-12-13T23:59:59+02:00"}]

Am i doing something wrong?

@l3pp4rd
Copy link
Member

l3pp4rd commented Feb 4, 2016

hi, the time.Time cannot be compared that simple. because it has a different memory address. You can create a time argument implementing Argument interface to compare time instances by their formats, or just as any value. Since I noticed that this question was raised few times before, I have added the example in README

@mantzas
Copy link
Author

mantzas commented Feb 4, 2016

I have followed the example but cannot get it working.
I have replaced the time with your example but still it did not work!
(Check out the project https://github.com/mantzas/incata and the test sql_writer_test.go)

@l3pp4rd
Copy link
Member

l3pp4rd commented Feb 5, 2016

In that case it means the reason is not the time.Time argument. but something else. The easiest way to find out - is to make an Any type to match any argument and see which one is failing (sqlmock could write that in error as an improvement):

type Any struct{}

func (a Any) Match(v driver.Value) bool {
    return true
}

Change one by one argument to Any{} and see what happens. I found out that it was Event.SourceID which is of uuid.UUID type. The reason why it is not matching is because this type when written to database value is converted to a simple string type - and sqlmock in your case tries to compare string and uuid.UUID interface.. which of course do not match. So your test should look like:

func TestSqlWriterWrite(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()

    ser := NewJSONSerializer()
    database, _ := NewDbFinalized(db, MSSQL)
    wr := NewSQLWriter(database, ser)

    event := NewEvent(uuid.NewV4(), getTestData(), "TEST", 1)

    payload, _ := ser.Serialize(event.Payload)

    mock.ExpectExec("INSERT INTO Event").
        WithArgs(event.SourceID.String(), event.Created, event.EventType, event.Version, payload).
        WillReturnResult(sqlmock.NewResult(1, 1))

    if err := wr.Write(*event); err != nil {
        t.Errorf("error was not expected while writing event: %s", err)
    }

    // we make sure that all expectations were met
    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expections: %s", err)
    }
}

The time is actually matched by type in sqlmock, my mistake. But in case if you have a complex types to match as SQL arguments, Argument interface suits it well.

I will also have a look why it becomes a string and maybe it is a common sql library feature, sqlmock should match it the same way as database values get converted., something for improvement. Leave the issue open for now

@mantzas
Copy link
Author

mantzas commented Feb 5, 2016

Perfect. this work very nice. Fantastic library by the way!!!

@l3pp4rd
Copy link
Member

l3pp4rd commented Feb 8, 2016

thanks, have fun with the library ;)

@mantzas
Copy link
Author

mantzas commented Feb 8, 2016

Hi, i have another problem.

i cannot make Query to work(sql_reader_test.go). The test expects the query to be the following:

  • `SELECT

    Id ,SourceId ,Created ,EventType ,Version ,Payload FROM Event WHERE SourceId = ?`.

  • the argument is of type uuid.UUID

i have setup the mock using the anytype wich returns always true but it still does not work.
what do i do wrong?

@l3pp4rd
Copy link
Member

l3pp4rd commented Feb 8, 2016

hi, ExpectQuery takes a regular expression string, not a string. so you either have to escape it properly, or simply use something like ExpectQuery('^SELECT (.*) FROM xxx") its a regular expression.

@mantzas
Copy link
Author

mantzas commented Feb 9, 2016

yes i tried but it did not work!

this regex matches my query expression when using a online tool:
regex: ^SELECT (.) FROM Event WHERE SourceId = (.)
against the query: SELECT Id ,SourceId ,Created ,EventType ,Version ,Payload FROM Event WHERE SourceId = ?

still it does not work!

sql_reader_test.go:40: there were unfulfilled expections: there is a remaining expectation which was not matched: ExpectedQuery => expecting Query or QueryRow which:

  • matches sql: '^SELECT (.) FROM Event WHERE SourceId = (.)'
  • is with arguments:
    0 - {}

what am i doing wrong?

@l3pp4rd
Copy link
Member

l3pp4rd commented Feb 9, 2016

Well you have to understand what you are doing @mantzas

func TestSqlReaderRead(t *testing.T) {

    // t.Skip("Not working yet!!!")

    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()

    var sourceID = uuid.NewV4()

    rows := sqlmock.NewRows([]string{"Id", "SourceId", "Created", "EventType", "Version", "Payload"})
    // rows.AddRow(columns...)
    mock.ExpectQuery("SELECT").
        WithArgs(sourceID.String()).
        WillReturnRows(rows)

    storage, _ := NewDbFinalized(db, MSSQL)
    marshaller := NewJSONMarshaller()
    reader := NewSQLReader(storage, marshaller)

    _, err = reader.Read(sourceID)
    if err != nil {
        t.Fatalf("unexpected err: %s", err)
    }

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

You have to simulate everything with sqlmock, what you expect, what it will return. see tests in sqlmock or examples. I cannot help you and I won't, if you keep asking without even looking how the library works. sqlmock returns errors through your *sql,DB, so check for errors, that is what you must do usually in go programs and especially in your tests. Also I see that, sourceID you store is of custom type, you must implement methods to any custom database type, to convert it to bytes or string instead so sql.DB would be able to read and write it.

@mantzas
Copy link
Author

mantzas commented Feb 9, 2016

thanks very much, got it.
I looked only at the examples on your the Github page which had no Query sample, and did not look in the examples folder which had a query sample. Maybe you could add one at the front to.
will not bother you again!

@mantzas mantzas closed this as completed Feb 9, 2016
@eoinahern
Copy link

having trouble testing count with this library

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants