I am using AutoFixture to mock an external library that doesn't always implement interfaces, but has a default ctor without parameters.
Currently, I am using Moq/AutoMoq framework like that:
mocker.GetMock<HeavyDependency>()
.Setup(x => x.GetData())
.Returns("TEST DATA");
I want to have the same behaviour with AutoFixture.AutoMoq. My code:
namespace AutoFixtureNUnit.TestsCs
{
public class HeavyDependency1
{
public HeavyDependency1() => Debug.WriteLine("HeavyDependency1");
}
public class HeavyDependency2
{
public HeavyDependency2() => Debug.WriteLine("HeavyDependency2");
}
public class MyClassWithHeavyDependency
{
private readonly HeavyDependency1 dep1;
private readonly HeavyDependency2 dep2;
public MyClassWithHeavyDependency() => Debug.WriteLine("MyClassWithHeavyDependency default.");
public MyClassWithHeavyDependency(HeavyDependency1 h1, HeavyDependency2 h2)
{
Debug.WriteLine("MyClassWithHeavyDependency injected.");
dep1 = h1;
dep2 = h2;
}
}
[TestFixture]
public class TestClass
{
private Fixture _fixture;
private Mock<HeavyDependency1> _heavyMock;
MyClassWithHeavyDependency _sut;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture
.Customize(new ConstructorCustomization(typeof(MyClassWithHeavyDependency), new GreedyConstructorQuery()))
.Customize(new AutoMoqCustomization(){ConfigureMembers = false});
_heavyMock = new Mock<HeavyDependency1>();
_fixture.Inject(_heavyMock.Object);
_sut = _fixture.Create<MyClassWithHeavyDependency>();
}
[Test]
public void TestMethod()
{
Assert.Pass("Your first passing test");
}
}
}
MyClassWithHeavyDependency has a ctor that takes dependent objects and code above calls that ctor.
So far so good. I am injecting the Mock of the dependent object and verifying calls.
The problem:
For the mocks that are Injected, the constructor is called with the Mock like: {Mock<AutoFixtureNUnit.TestsCs.HeavyDependency1:00000001>.Object}.
However, for all other types it is called with the parameter of {AutoFixtureNUnit.TestsCs.HeavyDependency2}. Which is not what I want and is not used by the current tests. Not a Moq object, right?
It is mocking my own interfaces as well.
Question:
Can I somehow specify that AutoFixture.AutoMoq should mock all ctor parameters that are not manually mocked by me?
Because Freezing/injecting every single one is not different from manual mock setup and requires a lot of code changes every time I add ctor parameter.
Actually, I can see HeavyDependency1 ctor called as well. Seems strange.
Related
I have created a wrapper class for the Microsoft DependencyInjection to simplify some of the calls in my application. I am trying to write unit tests that use Moq to insert objects into the dependency injection service.
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
public static class DiService
{
private static IServiceProvider diProvider;
private static Dictionary<Type, object> mockCollection = new Dictionary<Type, object>();
public static IServiceCollection ServiceCollection { get; } = new ServiceCollection();
public static bool UseTestMode { get; set; } = false;
public static T GetRequiredService<T>()
where T : class
{
if( UseTestMode )
{
if( mockCollection.ContainsKey(typeof(T)) )
{
return mockCollection[typeof(T)] as T;
}
}
if( diProvider == null )
{
diProvider = ServiceCollection.BuildServiceProvider();
}
return diProvider.GetRequiredService<T>();
}
public static void RegisterMock(Type interfaceType, object mockObjectInstance)
{
if( !mockObjectInstance.GetType().IsInstanceOfType(interfaceType) )
{
throw new InvalidCastException($"mockObjectInstance must be of type {interfaceType}");
}
if( mockCollection.ContainsKey(interfaceType) )
{
mockCollection[interfaceType] = mockObjectInstance;
}
else
{
mockCollection.Add(interfaceType, mockObjectInstance);
}
}
}
Testing related code
public interface ITestInterface
{
}
public class TestClass : ITestInterface
{
}
[Fact]
public void GetRequiredService_MoqObject_NormalOperation()
{
Mock<ITestInterface> mock = new Mock<ITestInterface>();
DiService.UseTestMode = true;
DiService.RegisterMock(typeof(ITestInterface), mock.Object);
ITestInterface testResult = DiService.GetRequiredService<ITestInterface>();
Assert.NotNull(testResult);
}
This works great for mocks that I great myself, but not when I try to use Moq. The InvalidCastException is thrown for Moq objects.
In the RegisterMock method, I haven't been able to figure out how to cast the Moq object to check if it implements the proper interface. The Moq object actually doesn't inherit from the interface it's mocking (the interface is ITestInterfaceProxy). I also can't figure out how to cast an object to a type specified by a variable.
Is there any way to actually perform the error check in RegisterMock?
Thanks ahead of time for your responses.
Addendum:
Based on Peter Csala's comment, I am adding this example of how I'm using the DiService above. I hope I haven't simplified it to the point of uselessness.
[Fact]
public void TestLoad()
{
DiService.UseTestMode = true;
Mock<IDataAccess> mockDataAccess = new Mock<IDataAccess>();
DiService.RegisterMock(typeof(IDataAccess), mockDataAccess.Object);
Data testData = GenFu.A.New<Data>();
mockDataAccess.Setup(mock => mock.LoadData(It.IsAny<string>()).Returns(testData);
// Assuming that inside MyViewModel.LoadData there is some process that generates an IDataAccess and calls IDataAccess.LoadData
MyViewModel viewModel = new MyViewModel();
Data loadedData = viewModel.LoadData("some id");
Assert.Equal(testData, loadedData);
}
Just to clarify certain things:
I am trying to write unit tests that use Moq to insert objects into the dependency injection service
In case of unit testing the DI is not in use. Rather you explicitly pass the mocked object to your system under test. For example:
Your System under test class
private readonly IDependency dependency;
public SampleUsage(IDependency dep)
=> dependency = dep;
Your test code
//Arrange
Mock<IDependency> mockedDep = new Mock<IDependency>();
mockedDep.Setup(...).Returns(...);
var sut = SampleUsage(mockedDep.Object);
//Act
var actualResult = sut.XYZMethod();
In case of integration or end-to-end testing you rely on the DI system, but not by replacing some components with a mocked one. Rather you are using different configuration options.
For example if you have a component that communicates with a 1st or 3rd party REST service then you should change the base address configuration of that service. That new address should point to a locally running http mock server. You can create one with a library like WireMock.NET.
I want to do something like this to provide methods from test classes to other test classes using composition.
public class SomeTestClass : IClassFixture<SomeService>
{
private readonly SomeService SomeService;
public SomeTestClass(SomeService someService)
{
SomeService = someService;
}
[Fact]
private void Test()
{
//....
}
public SomeData CreateSomeData()
{
// populate fields with something based on internal/service state
return new SomeData();
}
public void DoSomeAction(....)
{
// does action which modifies internal/service state
}
}
public class SomeConsumingClass : IClassFixture<SomeTestClass>
{
private readonly SomeTestClass SomeTestClass;
public SomeConsumingClass(SomeTestClass someTestClass)
{
SomeTestClass = someTestClass;
}
[Fact]
private void Test()
{
var data = SomeTestClass.CreateSomeData();
// ....
SomeTestClass.DoSomeAction(...)
}
}
The test in SomeTestClass passes but the test in SomeConsumingClass fails with a message
Class fixture type 'Requirements.SomeTestClass' had one or more unresolved constructor arguments: SomeService someService) (The following constructor parameters did not have matching fixture data: SomeTestClass someTestClass
It seems like a feature like this is not directly supported as it seems to be looking for a parameterless constructor. I intended to use this pattern for each test class, therefore I am looking for some good way to do something similar without too much boilerplate code. Any suggestions on how I could provide methods from the other test classes without inheritance?
EDIT:
Added some additional examples how I imagine myself using this
From the xUnit documentation on Class Fixtures (emphasis added):
Note that you cannot control the order that fixture objects are created, and fixtures cannot take dependencies on other fixtures. If you have need to control creation order and/or have dependencies between fixtures, you should create a class which encapsulates the other two fixtures, so that it can do the object creation itself.
One solution would be to move the CreateSomeData method to SomeService, and then change SomeConsumingClass so that it also implements IClassFixture<SomeService>.
However, it's worth pointing out this line from the documentation regarding when IClassFixture is appropriate:
When to use: when you want to create a single test context and share it among all the tests in the class, and have it cleaned up after all the tests in the class have finished.
From the description you've provided, it doesn't seem clear to me that IClassFixture is necessary here, since all you really want is the ability to call CreateSomeData from different test classes. A dead-simple alternative would be to just move GetSomeData to a utility class that can be directly called from any test fixture that needs it.
So I played around with possible solutions and was able to come up with a solution which allows for identical behavior
public class SomeTestClass
{
private readonly SomeService SomeService;
public SomeTestClass(SomeService someService)
{
SomeService = someService;
}
[Fact]
private void Test()
{
//....
}
public SomeData CreateSomeData()
{
// populate fields with something based on internal/service state
return new SomeData();
}
public void DoSomeAction(....)
{
// does action which modifies internal/service state
}
}
public class SomeDerivingTestClass : SomeTestClass
{
public SomeDerivingTestClass() : base(CreateSomeService())
{
}
private static SomeService CreateSomeService()
{
return new SomeService();
}
}
public class SomeConsumingClass : IClassFixture<SomeDerivingTestClass>
{
private readonly SomeTestClass SomeTestClass;
public SomeConsumingClass(SomeDerivingTestClass someTestClass)
{
SomeTestClass = someTestClass;
}
[Fact]
private void Test()
{
var data = SomeTestClass.CreateSomeData();
// ....
SomeTestClass.DoSomeAction(...)
}
}
Here is my Module:
public class LoggerModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument(
typeof(Type),
x => x.Request.ParentContext.Plan.Type);
}
}
So as you can see the NLogLogger is expecting the Type to be passed into the constructor.
This is my Unit Test:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var service = kernal.Get<ILogger>(new ConstructorArgument("type", typeof(int)));
Assert.That(service, Is.Not.Null);
}
It is throwing a null reference error on the kernal.Get<ILogger> so I can only assume I am not passing the constructor value correctly. How can I pass in a Type when using Get<T>?
So, this question as it seems relates to your other question.
The requirement in that question was to inject into NLogLogger the type of the object into which the it will be injected.
The registration in this case is assuming that this interface ILogger will not be resolved outside the context of a parent class into which it will be injected. And you are getting the exception because there is no parent class context when you directly attempt to resolve the ILogger interface.
I am assuming that in your unit test, your would like to test that this registration actually work. I would suggest the following:
First, create a class the you will use in your tests:
public class TestClass
{
private readonly ILogger m_Logger;
public TestClass(ILogger logger)
{
m_Logger = logger;
}
public ILogger Logger
{
get { return m_Logger; }
}
}
And then use such class in your unit tests like this:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var test_object = kernal.Get<TestClass>();
Assert.That(test_object.Logger, Is.Not.Null);
}
You can further verify that the NLogLogger actually used the TestClass class's name to construct the NLog logger. This might require the use of Reflection though, I am not sure.
In your Load method you can just set it up using Bind<ILogger>().To<NLogLogger>();
Given the following class and test
public class UserService
{
private IUserRepository _userRepo;
public UserService(IUserRepository userRepo)
{
_userRepo = userRepo;
}
public User Get(int id)
{
var user = _userRepo.Get(id);
if(user == null)
throw new CustomException();
return user;
}
}
Unit Tests:
[Fact]
public void MissingUser_ThrowsException()
{
// Arrange
var userService = new UserService(null);
// Act
Action result = userService.Get(0);
// Assert
result.Throws<CustomException>();
}
[Fact]
public void ExistingUser_ReturnsUser()
{
// Arrange
var user = new User()
{
Id = 0
};
var userRepo = new Mock<IUserRepository>();
userRepo
.Setup(m => m.Get(0))
.Return(user);
var userService = new UserService(userRepo.Object);
// Act
var result = userService.Get(0);
// Assert
Assert.Equal(user, result);
}
Is there a way to avoid passing in null parameters into the constructor when I know the dependencies will not be called in the test? If the class under test now requires a new constructor argument, I'd need to add another null parameter to this test and all other test that don't utilize that dependency.
Update:
I'm using Moq and XUnit. That is, I want to avoid using setup methods as I agree with the philosophy of XUnit. However, any mocking framework would still have the same problem.
I added another test that uses the mock. The case that I'm trying to avoid is having to deal with adding additional parameters to the constructor of the class under test when I don't need to.
If I were to add another dependency in the constructor of UserService that is used by the Get method, I would want only the second test to fail at run time. Currently, I would need to add another parameter to the ctor of UserService for both tests.
The more I think about this, the more I realize I want to use a IoC to construct my concrete (class under test). Is using an DI/IoC container in unit tests recommended?
Although it is odd that you aren't using a mocking framework, it sounds like your question relates to another issue. Many unit test will be written and the constructor for the class under test may change. What you are asking, I think, is how do you avoid the busy work of changing each and every test when you make changes to the constructor signature of the class under test?
One way to avoid this is to use a helper class to manage the construction of your test instances. Here's a simple example:
public class UserServcieMockManager
{
//mock objects here if you're using a mocking framework
public UserService GetServiceForTesting()
{
return new UserService(null); //here's where the mocks would be used
}
}
The reason I've called this class "Mock Manager" is because this is also where you would instantiate your mocks. Then when the constructor signature changes, you only have to change the one method that creates the test instance.
This type of helper class also becomes very useful as a way to centralize the setup logic for mocking scenarios that are reused between tests.
The more I think about this, the more I realize I want to use a IoC to construct my concrete (class under test). Is using an DI/IoC container in unit tests recommended?.
I prefer creation of class under test within Setup or Init method and see no reason to avoid doing it.
If you want to use IoC/DI to create your class under test, you can use AutoMoq (see on GitHub, NuGet package).
There is an exmple of usage:
[TestClass]
public class ServiceConsumerTestWithAutoMoq
{
[TestMethod]
public void DoA()
{
//arrange
var mocker = new AutoMoqer();
var sut = mocker.Create<ServiceConsumer>();
//act
sut.DoA();
//assert
mocker.GetMock<IServiceA>().Verify(it => it.Do(), Times.Once());
mocker.GetMock<IServiceB>().Verify(it => it.Do(), Times.Never());
}
[TestMethod]
public void DoB()
{
//arrange
var mocker = new AutoMoqer();
var sut = mocker.Create<ServiceConsumer>();
//act
sut.DoB();
//assert
mocker.GetMock<IServiceA>().Verify(it => it.Do(), Times.Never());
mocker.GetMock<IServiceB>().Verify(it => it.Do(), Times.Once());
}
}
public interface IServiceConsumer
{
void DoA();
void DoB();
}
public class ServiceConsumer : IServiceConsumer
{
public IServiceA serviceA { get; set; }
public IServiceB serviceB { get; set; }
public ServiceConsumer(
IServiceA serviceA,
IServiceB serviceB)
{
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void DoA()
{
serviceA.Do();
}
public void DoB()
{
serviceB.Do();
}
}
public interface IServiceA
{
void Do();
}
public interface IServiceB
{
void Do();
}
There is another library Moq.AutoMocker that is developed by member of Moq Team, Tim Kellogg.
But I'd rather use Setup or Init method to create class under test.
There is code example that I would use to solve your issue.
[TestClass]
public class ServiceConsumerTestWithInit
{
private Mock<IServiceA> serviceAMock;
private Mock<IServiceB> serviceBMock;
private IServiceConsumer sut;
[TestInitialize]
public void Initialize()
{
serviceAMock = new Mock<IServiceA>();
serviceBMock = new Mock<IServiceB>();
sut = new ServiceConsumer(
serviceAMock.Object,
serviceBMock.Object);
}
[TestMethod]
public void DoA()
{
//act
sut.DoA();
//assert
serviceAMock.Verify(it => it.Do(), Times.Once());
serviceBMock.Verify(it => it.Do(), Times.Never());
}
[TestMethod]
public void DoB()
{
//act
sut.DoB();
//assert
serviceAMock.Verify(it => it.Do(), Times.Never());
serviceBMock.Verify(it => it.Do(), Times.Once());
}
}
Instead of passing null, I'd mock IUserRepository and simply pass the mocked object.
This way a check against null doesn't throw e.g. an ArgumentException... (if you would implement such checks which is pretty handy in DI code).
If you still do not want that, implement another empty ctor for testing. Mark it internal and make the assembly internals visible to your test project. Or protected and have a derived test class.
No there is no way you can force the caller to always pass a not null value.
The best you can do is use factory pattern to pass IRepositoryFactory to the constructor so you will only have 1 parameter and will need to check for null for only that parameter.
Your RepositoryFactory will return the types for each repository you will need.
How to implement a generic RepositoryFactory?
It sound like you are looking for a Mock framework.
Personally, I Prefer Rhino Mocks
I am not sure I remember the syntax for it, but it is very easy. If I am not mistaking it is something like:
var mockedUserReop = MockRepository.GenerateMock<IUserRepository >();
The full method will be:
[TestInitialize, SetUp]
public void TestInitilize()
{
var mockedUserReop = MockRepository.GenerateMock<IUserRepository >();
UserService = new UserService(mockedUserReop );
}
Typically when I need to mock out a class for testing, I'll use a library such as Rhino Mocks. Here I have a class called MyService that expects a IEmailSender.
public class MyService
{
private readonly IEmailSender sender;
public MyService(IEmailSender sender)
{
this.sender = sender;
}
public void Start()
{
this.sender.SendEmail();
}
}
If I needed to test the interaction between these two objects, my test would look something like this:
[TestMethod]
public void Start_Test_Using_Rhino_Mocks()
{
IEmailSender emailSender = MockRepository.GenerateMock<IEmailSender>();
MyService service = new MyService(emailSender);
service.Start();
emailSender.AssertWasCalled
(
x => x.SendEmail(),
c => c.Repeat.Once()
);
}
In the test above, I'm using Rhino Mocks to generate the mock and assert that the SendEmail() method was called once.
But what if I could not use Rhino Mocks and had to create manual mocks?
public class MockEmailSender : IEmailSender
{
public void SendEmail()
{
}
}
[TestMethod]
public void Start_Test_Using_Manual_Mocks()
{
MockEmailSender emailSender = new MockEmailSender();
MyService service = new MyService(emailSender);
service.Start();
// How do I test the interaction?
}
With the mock that I created manually, how would I verify that the SendEmail() method was called? I could put my assertions in the SendEmail() method of the mock, but that would make the test hard to understand since I don't immediately see what's going on when I look at the test.
A very simple solution would have your manual mock just be a stateholder, with counters for the calls to each method. But it's fragile ...
public class MockEmailSender : IEmailSender
{
public int SendCount = 0;
public void SendMail(...)
{
SendCount++;
}
// ... other IEmailSender methods ...
}
Then just query SendCount after making your method call, and making sure that it's == 1.
Remember, Rhino Mocks is creating this dynamically for you -- if you do it manually you have to react to interface changes before compile time, by hand.
I think that you have no other option than setting a flag in "SendEmail()", and checking that flag from the test throgh a new method of MockEmailSender like "sendMailWasInvoked()" or something like this (which is in fact a kind of "verify").
You can extend this to count the number of invokations, parameters...
well i would advise against creating any manual Mocks (because if you add new method to interface, it gets broken).
if you really have to do it, when expose some counter/bool in your MockEmailSender and you can Assert it later on.
Assert.IsTrue(emailSender.IsCalled)