Mocking a dependency with AutoFixture - c#

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:
My system under test can call the delegate and it will get a mock of IDbConnection
On which I can then call CreateCommand, which will get me a mock of IDbCommand
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?

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());

You have to Freeze the Mock<IDbCommand> as well – and setup the mock object (as a Stub) to return the existing dataReaderMock.Object instance.
If you add the following to the Arrange phase of you test, the test will pass:
var dbCommandStub =
fixture
.Freeze<Mock<IDbCommand>>()
.Setup(x => x.ExecuteReader())
.Returns(dataReaderMock.Object);

While the solution from Nikos works I would not I do not recommend mocking ado.net.
In my opinion your tests will probably be hard to understand, maintain and will not give you the confidence your tests should give you.
I would consider testing your data layer by going all the way to the database even though it is slower.
I would recommend reading this article regarding best practices for mocking:
http://codebetter.com/jeremymiller/2006/01/10/best-and-worst-practices-for-mock-objects/
Don't mock others:
http://aspiringcraftsman.com/2012/04/01/tdd-best-practices-dont-mock-others/
I don't know your exact situation but anyways I wanted to share this.

Related

Simple Injector, can't override existing registration

I am currently using Simple Injector for the first time. In my .NET project I am running test and mocking data returned from a web service and registering the object to the container like so
_container.Register<IWebServiceOrder>(() => mock.Object, Lifestyle.Transient);
This works fine. But in my tests I want to test the behavior of the system on a second call to the web service that will contain updated data, so the mock object will need to be updated.
By default Simple Injector does not allow Overriding existing registrations but the official website states it is possible to change this behavior like below.
https://simpleinjector.readthedocs.org/en/latest/howto.html#override-existing-registrations
container.Options.AllowOverridingRegistrations = true;
Unfortunately i still get an error when i try to register the object a second time even with the above code.
The container can't be changed after the first call to GetInstance, GetAllInstances and Verify
Any ideas on why this is happening?
Replacing an existing registration after you already worked with the container hardly ever has the behavior you would expect (and this holds for all DI libraries) and that's the reason why the Simple Injector container is locked. This is described in more details here (as #qujck already pointed out).
First of all, if you are writing unit tests, you shouldn't use a container at all. Your unit tests should create the class under test themselves, or you extract this logic to a convenient factory method, such as:
private static MailNotifier CreateMailNotifier(
IDeposit deposit = null, ISendMail mailSender = null, ILog logger = null)
{
return new MailNotifier(
deposit ?? Substitute.For<IDeposit>(),
mailSender ?? Substitute.For<ISendMail>(),
logger ?? Substitute.For<ILog>());
}
This factory method is a variation to the Test Data Builder pattern.
By making use of optional parameters, it allows the unit test to specify only the fake implementation it requires during testing:
public void Notify_WithValidUser_LogsAMessage()
{
// Arrange
var user = new User();
var logger = new FakeLogger();
MailNotifier sut = CreateMailNotifier(logger: logger);
// Act
sut.Notify(user);
// Assert
Assert.AreEqual(expected: 1, actual: logger.LoggedMessages.Count);
}
If you use a container, because creating the class under test by hand is too cumbersome, it indicates a problem in your class under test (most likely a Single Responsibility Principle violation). Prevent using tools to work around problems in your design; your code is speaking to you.
For integration tests however, it is much more usual to use the container, but in that case you should simply create a new container for each integration test. This way you can add or replace the IWebServiceOrder without any problem.

How do I record and replay method calls in c#.net for isolation testing of legacy code

I have a repository and a consumer of that repository in some legacy code.
The consumer makes multiple method calls to the repository.
Each method call returns a huge resultset.
I do have an integration test that checks how the consumer and repository behave together, but it isn't good enough for me - it relies on a database connection, is painfully slow, and doesn't help me know whether the test fails because of changes to the repository, database, or consumer.
I'd like to convert this integration test to test the consumer in isolation - independent of the implementation of the repository.
But because it is legacy code the behaviour of which I do not fully understand yet and because the resultsets are huge, I can't stub out the repository by hand. If it were possible to write this by hand it would look like
var mockRepository = new Mock<IRepository>();
mockRepository.SetUp(r => r.GetCustomersInMarket(marketId: 3))
.Returns(
new List<Customer> {
new Customer {
...
},
new Customer {
...
},
... x 100 // large dataset
});
mockRepository.SetUp(r => r.GetProductsInMarket(marketId: 3))
.Returns(
...
);
... x 15 // many different calls need to be set up
var testee = new Consumer(mockRepository.Object); // using dependency injection
var report = testee.GenerateReport();
AssertReportMatchesExpectations(report); // some assertions
So what I'd prefer to do is (once)
var recordingProxy = new RecordingProxy<IRepository>(new Repository());
var testee = new Consumer(recordingProxy);
var report = testee.GenerateReport();
var methodCallLog = recordingProxy.GetLog();
and thereafter
var methodCallLog = GetStoredMethodCallLog(); // load persisted log from file or similar
var replayingProxy = new ReplayingProxy<IRepository>(methodCallLog);
var testee = new Consumer(replayingProxy);
var report = testee.GenerateReport();
AssertReportMatchesExpectations(report); // some assertions
I have started working on a generic tool to act as a proxy and record and replay traffic that goes across interface boundaries to solve this problem in general.
Is there already anything like this out there?
Are there other ways to solve the problem of stubbing repositories
to return large datasets
when the content of the dataset can only be understood by observing existing behaviour (because the author's intent is not clear).
If not, I'll be posting my tool as an answer to this question.

Moq NHiberNate ISession.Get doesn't call mock session object

I am new to NHibernate and even newer to MOQ (or other similar frameworks). After searching online day and night (google + stackoverflow + others), I am turning here for help.
The scenario is (should be) simple. I am trying to unit test a call on a C# WCF service that uses NHibernate as the ORM layer. The method, after doing some initial work, finds a database to connect to, and then calls on the SessionProvider (a manager of session factories) to return a nhibernate session for a sharded DB. I am then trying to use ISession.Get<>() to retrieve an object from the database aand then do some work. The problem is that the GUID (the key for the entry that I am looking up in the db) is generated at the begining of the call and I have no way of knowing what it might be beforehand outside the scope of the WCF call. Hence, I cannot use sqllite or other techniques to pre-populate the necessary data to control the test. What I was hoping for was that I can somehow mock (inject a fake layer to?) the call to Session.Get to return an invalid object which should cause the WCF call to throw.
Here's the test code snippet:
var testRequest = ... (request DTO)
var dummyBadObject = ... (entity in DB)
var mock = new Mock<ISession>(MockBehavior.Strict);
mock.Setup(m => m.Get<SampleObject>(It.IsAny<Guid>())).Returns(dummyBadObject);
var exception = Assert.Throws<FaultException>(() => applicationService.SomeMethod(testRequest));
Assert.AreEqual(exception.Code.ToString(), SystemErrorFault.Code.ToString());
When I run this test, instead of interacting with the mock ISession object, the app service code calls the Get on the actual ISession object from the session factory, connects to the database and gets the right object. Seems like I am missing something very basic about mocks or injection. Any help will be appreciated.
Thanks,
Shawn
Based on our comments, the problem is that mocks are completely different from how you thought of them.
They don't magically intercept creations of classes derived from an interface. They are just dynamic implementations of it.
Creating a Mock<ISession> is not much different from creating a class that implements ISession. You still have to inject it in the services that depend on it.
You'll probably have to review your whole stack, as the capability to do this depends on a good decoupled design.
Suggested read: Inversion of control
I re-designed the components in my application to have a ServiceContext object which in turns holds all the other (what used to be static) components that the application uses. In this case, this would be the session provider (or the ISessionFactory cache), and similarly a WCF channel factory cache. The difference is that the ServiceContext provides methods to override the default instances of the different components allowing me to replace them with mock ones for testing and restoring the original ones when testing is done. This has allowed me to create a test where I mock all the way from the session cache to the ISession.Get/Save/Load etc.
var mockDatabaseSessionFactory = new Mock<DatabaseSessionManager>(MockBehavior.Strict);
var mockSession = new Mock<ISession>(MockBehavior.Strict);
var mockTransaction = new Mock<ITransaction>(MockBehavior.Strict);
mockDatabaseSessionFactory.Setup(x => x.GetIndividualMapDbSession()).Returns(mockSession.Object);
mockDatabaseSessionFactory.Setup(x => x.GetIndividualDbSession(It.IsAny<UInt32>())).Returns(mockSession.Object);
mockDatabaseSessionFactory.Setup(x => x.Dispose());
mockSession.Setup(x => x.BeginTransaction()).Returns(mockTransaction.Object);
mockSession.Setup(x => x.Dispose());
mockTransaction.Setup(x => x.Commit());
mockTransaction.Setup(x => x.Dispose());
// Setups to allow for the map insertion/deletion to pass
mockSession.Setup(x => x.Get<IndividualMap>(It.IsAny<string>())).Returns((IndividualMap)null);
mockSession.Setup(x => x.Load<IndividualMap>(It.IsAny<string>())).Returns((IndividualMap)null);
mockSession.Setup(x => x.Save(It.IsAny<IndividualMap>())).Returns(new object());
mockSession.Setup(x => x.Delete(It.IsAny<IndividualMap>()));
// Our test condition for this test: throw on attempt to save individual
mockSession.Setup(x => x.Save(It.IsAny<Individual>()))
.Throws(new FaultException(ForcedTestFault.Reason, ForcedTestFault.Code));
// Test it - but be sure to back up the previous database session factory
var originalDbSessionFactory = ServiceContext.DatabaseSessionManager;
ServiceContext.OverrideDatabaseSessionManager(mockDatabaseSessionFactory.Object);
try
{
var exception = Assert.Throws<FaultException>(() => applicationService.AddIndividual(addIndividualRequest));
Assert.IsTrue(ForcedTestFault.Code.Name.Equals(exception.Code.Name));
}
catch (Exception)
{
// Restore the original database session factory before rethrowing
ServiceContext.OverrideDatabaseSessionManager(originalDbSessionFactory);
throw;
}
ServiceContext.OverrideDatabaseSessionManager(originalDbSessionFactory);
ServiceContext.CommunicationManager.CloseChannel(applicationService);
Luckily the code design wasn't too bad o_O :) so i re-factored this bit easily and now code coverage is at 100! Thanks Diego for nudging me in the right direction.

Mocking TransactionTemplate from Spring.Net with Rhino mocks

I'm trying to create mock of TransactionTemplate
var tTemplate = MockRepository.GenerateMock<TransactionTemplate>();
var tDelegate = MockRepository.GenerateMock<ITransactionCallback>();
tTemplate.Expect(x => x.Execute(tDelegate)).IgnoreArguments().Throw(new Exception());
on last line i get NullPointerException from
at Spring.Transaction.Support.TransactionTemplate.Execute(ITransactionCallback action)
any idea what may be the reason?
The TransactionTemplate class in Spring.Net doesn't have virtual methods so RhinoMocks is unable to override the Execute method when you create the mock.
What this means is that you're not actually stubbing out the Execute method but calling through to the real method. That Execute method calls out to an IPlatformTransactionManager object which you haven't yet supplied and thus the null exception occurs.
Given that the Execute method is part of the ITransactionOperations interface, you may be able to get away with creating a mock ITransactionOperations object and using that in the rest of your test.
Alternatively you could try providing a mock IPlatformTransactionManager to the TransactionTemplate class, and also an ITransactionCallback.DoInTransaction() implemetation for using tDelegate.Stub().Do() syntax.
Something like this:
var transactionManager = MockRepository.GenerateMock<IPlatformTransactionManager>();
var mockDelegate = MockRepository.GenerateMock<ITransactionCallback>();
mockDelegate.Stub(t => t.DoInTransaction(null)).IgnoreArguments().Do(...);
var template = new TransactionTemplate(transactionManager);
template.Execute(mockDelegate);

Rhino Mocks Stub Method not working

Why won't this test method work? I keep getting requires a return value or an exception to throw.
public AuthenticateResponse Authenticate(string username, string password)
{
string response = GetResponse(GetUrl(username, password).ToString());
return ParseResponse(response);
}
[TestMethod()]
[ExpectedException(typeof(XmlException))]
public void Authenticate_BadXml_ReturnException()
{
MockRepository mockRepository = new MockRepository();
SSO sso = mockRepository.Stub<SSO>();
sso.Stub(t => t.GetResponse("")).Return("<test>d");
AuthenticateResponse response = sso.Authenticate("test", "test");
}
Your repository is still in "record" mode. You're mixing record/replay semantics (the "old" way of doing things) with the newer AAA (arrange/act/assert) style.
Instead of creating your own repository, simply use:
var sso = MockRepository.GeneateStub<SSO>();
Everything should work fine now.
Your last line is calling the Authenticate method on your stub object, you haven't set up a return or value or exception to throw when calling it, so Rhino Mocks doesn't know what the stub should do and it causes an error. You probably don't want to call a method on your stub - that seems kind of pointless to me, is there another object (that you're actually testing in this test) that you should be calling a method on?
Is that your whole test? If so, your test makes no sense. The only object in your test is the one you're stubbing--where is the subject of the test?
If you're trying to test the SSO class, you absolutely never want to mock/stub it. If SSO has one or more dependencies, use the mocking framework to set up canned interactions between those dependencies and your SUT. That is the exact purpose of a mocking framework.

Categories

Resources