-
Notifications
You must be signed in to change notification settings - Fork 3
How does it work
Normally you'd mock a IDbConnection
and Setup
, Verify
or both against that mock. Moq, however, cannot intercept extension methods, as is the case with Dapper calls. So this approach won't work.
Dapper does leverage the standard .net DAO types for database access however. So invoking the Dapper Query()
method at some point will call DbCommand.ExecuteReader()
. Dapper effectively is a set of (very good and efficient) helper methods over DbCommand
, etc. That's an over simplification, but not incorrect for understanding how this library works.
Dapper.MoqTests effectively reverse engineers the calls made to DbCommand
by Dapper.
So to summarise, your production code calls Dapper methods on the MockDbConnection
. Dapper does it's normal thing, but using a MockDbCommand
, provided by MockDbConnection
. This command then finds the appropriate Dapper method that would have been used to invoke it, that's the reverse engineering bit.
The next step is to allow for the Dapper extension method call to be intercepted by Moq. We cannot call the extension method as this won't be monitored by Moq. So we've implemented 'mirrors' of the Dapper extension methods on the MockDatabase
type, which is a Moq'd instance under the MockDbConnection
. The MockDbCommand
can then call the appropriate instance method, such as QueryAsync()
, and it will be seen/intercepted as appropriate by Moq. Even though these are defined as extension methods, .net will always prefer the implementation on the type rather than the extension method equivalent.
So as long as the implementations match the Dapper extension method, everything will work fine.
This approach is lossy however, it can be possible to loose information along the way, such as the generic type argument provided to QueryAsync()
. Whilst this has been resolved for a lot of cases it's not fool proof.
These are being investigated as they're identified.