Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking a dependency with AutoFixture

I've recently started using AutoFixture+AutoMoq and I'm trying to create an instance of Func<IDbConnection> (i.e., a connection factory).

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var connectionFactory = fixture.Create<Func<IDbConnection>>();

This seems to work rather well:

  1. My system under test can call the delegate and it will get a mock of IDbConnection
  2. On which I can then call CreateCommand, which will get me a mock of IDbCommand
  3. On which I can then call ExecuteReader, which will get me a mock of IDataReader

I now want to perform additional setups on the mock of IDataReader, such as make it return true when Read() is called.

From what I've read, I should be using Freeze for this:

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();

dataReaderMock.Setup(dr => dr.Read())
                      .Returns(true);

This doesn't seem to meet my expectations though. When I call IDbCommand.ExecuteReader, I'll get a different reader than the one I just froze/setup.

Here's an example:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//true - Create<IDataReader> retrieves the data reader I just mocked
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDataReader>());

//false - IDbCommand returns a different instance of IDataReader
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());

What am I doing wrong? How do I get other fixtures, such as IDbCommand, to use the mocked instance of IDataReader?

like image 397
dcastro Avatar asked Jul 31 '14 09:07

dcastro


People also ask

What is AutoFixture C#?

AutoFixture is designed to make Test-Driven Development more productive and unit tests more refactoring-safe. It does so by removing the need for hand-coding anonymous variables as part of a test's Fixture Setup phase. Among other features, it offers a generic implementation of the Test Data Builder pattern.

What is AutoMoq?

AutoMoq is an extension that turns AutoFixture into an Auto-Mocking Container using the Moq dynamic mock library. There's also a similar extension for AutoFixture that enables auto-mocking with Rhino Mocks.

What is AutoFixture Xunit?

AutoFixture is a tool designed to make Test-Driven Development more productive and unit tests more refactoring-safe.

What is mock setup?

With mocks, you can set up the object, including giving parameters and return values on method calls and setting properties. You can also verify that the methods you set up are being called in the tested code. This ensures that the flow of the program is as expected.


1 Answers

As of 3.20.0, you can use AutoConfiguredMoqCustomization. This will automatically configure all mocks so that their members' return values are generated by AutoFixture.

E.g., IDbConnetion.CreateCommand will be automatically configured to return an IDbCommand from the fixture, and IDbCommand.ExecuteReader will be automatically configured to return an IDataReader from the fixture.

All of these tests should pass now:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//all pass
Assert.Same(dataReaderMock.Object, fixture.Create<IDataReader>());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbConnection>().CreateCommand().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<Func<IDbConnection>>()().CreateCommand().ExecuteReader());
like image 63
dcastro Avatar answered Sep 21 '22 14:09

dcastro