DATA-DOG / go-sqlmock

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

Working with multiple Prepares leads to unmatched expectations #228

Open eellenoff opened 4 years ago

eellenoff commented 4 years ago

go version go1.14.2 darwin/amd64

github.com/DATA-DOG/go-sqlmock v1.4.1

I'm trying to mock out a piece of code which uses two prepared statements to execute a series of queries. However, sqlmock seems to get confused if I create my ExpectPrepares (A&B), then create my Expects (A&B), then execute my queries (A&B) against the Expects.

On the other hand, if I create ExpectPrepare (A), create Expect (A), query against Expect (A), and then repeat for B it works. Unfortunately, the product code I'm trying to mock out isn't amenable to this pattern.

Shouldn't all three cases in this example work?

https://play.golang.org/p/k-sxKxGnd0Q

l3pp4rd commented 4 years ago

yes, sadly the reason is:

  1. the rows were not closed or garbage collected for the q1P.
  2. in go sql standard library the connection is held on Rows until they are closed. So this blocks connection.
  3. that is why, standard sql library tried to open another connection, then it fired a PrepareContext again to the sqlmock and then it failed, since we were expecting Query instead of Prepare.

your test example modified to close rows https://play.golang.org/p/ohpOe4J31mh

I do not know why go does that, it has the TODO in the code to fix it there and call Preparer interface instead to sqlmock driver. we could then adjust it.

Now the only option would be to ignore that Prepare call if the expectation was already met, but in such case, we may also fail some tests where the second call to prepare was not expected. Sadly I do not know how to fix this properly. But probably worth having this issue open for others to be aware of.

I do not have much free time these days, so if anyone could contribute, this would be helpful to the library