Moq Triqs – Mocking an IDbCommand
Knocked up this handy little extension method last week to help us mock the use of IDbCommand (and its associated classes) to test some ADO.NET code. The idea is that you pass in the text and type of the command, and an anonymous type representing the parameter names and values that you expect it to be called with.
public static Mock<IDbCommand> CreateDbCommand<T>(this MockFactory factory, string commandText, CommandType commandType, T parameters) where T : class { var cmd = factory.Create<IDbCommand>(); var parms = factory.Create<IDataParameterCollection>(); var pq = new Queue<IDbDataParameter>(); foreach (var prop in parameters.GetType().GetProperties()) { object val = prop.GetValue(parameters, null); var par = factory.Create<IDbDataParameter>(); par.ExpectSet(p => p.ParameterName, prop.Name); par.ExpectSet(p => p.Value, val ?? DBNull.Value); pq.Enqueue(par.Object); parms.Expect(c => c.Add(par.Object)).Returns(0); } cmd.ExpectSet(c => c.CommandText, commandText); cmd.ExpectSet(c => c.CommandType, commandType); cmd.ExpectGet(c => c.Parameters).Returns(parms.Object); cmd.Expect(c => c.CreateParameter()).Returns(() => pq.Dequeue()); cmd.Expect(c => c.Dispose()); return cmd; }
So if you have a stored procedure called “GetFooByID” and you expect to pass it an “@id” parameter with a value of 1, you simply construct your mock like this:
var cmd = mockFactory.CreateDbCommand("GetFooByID", CommandType.StoredProcedure, new { id = 1 });
… and then, of course, set up your expectations about how the command will be executed (presumably with an ExecuteReader in this scenario).
Note that is code is still using the “Expect” syntax in Moq rather than the new “Setup” syntax, so your mileage may vary. It’s certainly made life easy for us when mocking ADO.NET commands.
Comments
# Eden Ridgway
28/04/2010 1:30 PM
I just wanted to drop you a note to say thank you for writing this post. It is a great solution and really has made our tests much more elegant.
# mabster
28/04/2010 1:37 PM
You're more than welcome, Eden - it did the same for us! :)
# Paul
8/03/2016 2:26 AM
Great job, I've updated it for the latest version of Moq for you.
public static Mock<IDbCommand> CreateDbCommand<T>(this MockRepository repository, string commandText, CommandType commandType, T parameters) where T : class
{
var cmd = repository.Create<IDbCommand>();
var parms = repository.Create<IDataParameterCollection>();
var pq = new Queue<IDbDataParameter>();
foreach (var prop in parameters.GetType().GetProperties())
{
object val = prop.GetValue(parameters, null);
var par = repository.Create<IDbDataParameter>();
par.SetupSet(p => p.ParameterName = prop.Name);
par.SetupSet(p => p.Value = val ?? DBNull.Value);
pq.Enqueue(par.Object);
parms.Setup(c => c.Add(par.Object)).Returns(0);
}
cmd.SetupSet(c => c.CommandText = commandText);
cmd.SetupSet(c => c.CommandType = commandType);
cmd.SetupGet(c => c.Parameters).Returns(parms.Object);
cmd.Setup(c => c.CreateParameter()).Returns(() => pq.Dequeue());
cmd.Setup(c => c.Dispose());
return cmd;
}