Skip to content

How does it work

Simon Laing edited this page Aug 19, 2019 · 12 revisions

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.

Connecting the dots

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.

How does Moq know about the calls?

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.

Difficulties with the approach

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.

Clone this wiki locally