I am new to unit testing and trying to figure out a bit more about MOQ.
Is there an API that allows me to mock future instances of some type?
I mean,
Let's say I am mocking a class. Inside that class I use the new operator to create a new instance of an object.
I want to mock all future instances of the same type of that object that will be created within that class in the future, is there such API?
I tried to look into MOQ documentation but there is no such example. Help anyone?
Don't use new, use dependency injection and a factory. Then you can make your class create mocks:
internal class SubjectUnderTest
{
public SubjectUnderTest( IProductFactory factory )
{
_factory = factory;
}
public void DoStuff()
{
var product = _factory.CreateProduct(); // this creates a mocked product (where you new'ed something before)
product.DoSomeThing(); // this calls into the mock product
}
private readonly IProductFactory _factory;
}
A test would then look like this
var mockFactory = new Mock<IProductFactory>();
mockFactory.Setup( x => x.CreateProduct() ).Returns( () =>
{
var mockProduct = new Mock<IProduct>();
// TODO setup product mock here
return mockProduct.Object;
} );
var instance = new SubjectUnderTest( mockFactory.Object );
instance.DoStuff(); // <- uses the factory mock defined above to create a mocked product and calls into the mocked product
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'm pretty new with using Moq and I'm running into an issue were one of my method calls is returning null despite the fact that I have mocked it.
I am mocking the following interfaces.
public interface IUnitOfWorkFactory
{
IUnitOfWork Create(KnownDbContexts knownDbContexts);
}
public interface IUnitOfWork : IDisposable
{
Task SaveChanges();
IRepository Repository { get; }
}
Then in my unit test code it looks like this.
_uowFactoryMock.Setup(x => x.Create(It.IsAny<KnownDbContexts>()))
.Returns(It.IsAny<IUnitOfWork>());
The code I'm testing looks like this.
using (var uow = _unitOfWorkFactory.Create(KnownDbContexts.UserDefined1))
{
// At this point 'uow' is null.
}
Why is IUnitOfWorkFactory.Create returning null?
In your current code, the method Create of the mocked factory returns an object of type It.IsAny<IUnitOfWork>.
However you want your mocked factory to return a mock of the unit of work, as such:
var uowMock = new Mock<IUnitOfWork>();
// here mock uowMock's methods (ie SaveChanges) in the same way it is done below for the factory
_uowFactoryMock.Setup(x => x.Create(It.IsAny<KnownDbContexts>()))
.Returns(uowMock.Object);
Let's assume we have the following setup:
public interface IBase
{
void Foo();
}
public class Base : IBase
{
public virtual void Foo()
{
Console.WriteLine("Called Base.Foo()");
}
}
public interface IChild : IBase
{
void Bar();
}
public class Child : Base, IChild
{
public virtual void Bar()
{
Console.WriteLine("Called Child.Bar()");
}
}
When mocking the Child object everything works fine:
var child = new Mock<Child> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Output is:
Called Child.Bar()
Called Base.Foo()
But when mocking the IChild interface nothing is printed to the console:
var child = new Mock<IChild> { CallBase = true };
child.Object.Bar();
child.Object.Foo();
Let's assume I can't mock the Child object because there is no parameterless constructor (dependency injection).
I know that I could just do the following:
child.Setup(c => c.Bar()).Callback(() =>
{
// Copy paste bar-method body
});
child.Setup(c => c.Foo()).Callback(() =>
{
// Copy paste foo-method body
});
But that would be very ugly.
Is there a clean solution using Mock<IChild>?
As long as you are mocking the interface, you have no access or information about the real classes which explains why you don't get any output (but I guess you understood that).
Unfortunately if you choose to mock an interface (which by definition have no behavior), the only way to make things happen is to Setup the method the way you did.
Another "dirty" way would be to use method extension to your child and base class if the content of the method is only using public attributes and method.
public static class ChildExtension
{
public static void Bar(this Child child)
{
Console.WriteLine("Called Child.Bar()");
}
}
You are going to the wrong direction
Mock exists to help in unit testing. For example if you want to test the method Save() of a class which uses a wrapper over a DbContext like the following:
interface IRepository
{
void PersistData(object dataToBeSaved);
}
class DataSaver
{
private IRepository _repository;//this object's method PersistData makes a call to a database
public DataSaver(IRepository repository)
{
_repository = repository;
}
public void Save(object dataToBeSaved)
{
_repository.PersistData(dataToBeSaved);
}
}
In this case, in order to test the method Save of the DataSaver you will do a call to it in a unit test, but the problem you will face when doing this is that the method will actually try to save the data using the repository objet. Unless you send a fake repository your unit test will save data every time you run it, and this is not what a unit test should be doing. It should not run a method from a concrete IRepository object, but it should still call it's method.
What you could do in this case to avoid saving of an object is to make another class which implements IRepository only for testing:
class DummyRepository : IRepository
{
public object DataJustSaved { get; set; }
public void PersistData(object dataToBeSaved)
{
DataJustSaved = dataToBeSaved;
}
}
Now in your unit test you will do something like this:
var dummyRepository = new DummyRepository();
var dataSaver = new DataSaver(dummyRepository);
var savedObject = new Object();
var expectedObject = savedObject;
dataSaver.Save(savedObject);//test the save method
var actualObject = dummyRepository.DataJustSaved;
Assert.AreEqual(expectedObject, actualObject);//verify that the data was passed to the PersistData method
Here the Mock helps
It would be quite difficult to make a fake class for each unit test, that is what alternative mock offers:
var dummyRepository = new Mock<IRepository>();
var dataSaver = new DataSaver(dummyRepository.Object);
var savedObject = new Object();
dataSaver.Verify(x => x.PersistData(savedObject), Times.Once());// just make sure the method PersistData was invoked with the expected data and only once.
The reason Mock exists is to make pretty smart dummies for you, to write unit tests without a great impact but which can reveal bugs, and keep the code doing what only it's supposed to do.
In your case, if you really want to call the actual method of the concrete object:
child.Setup(c => c.Bar()).Callback(() =>
{
Console.WriteLine("Called Child.Bar()");
});
Then it means that you should not even try to use the mock to reproduce the exact same implementation of the object you mock. What would be the use of the mock if it is doing the same thing as the actual object?
In this case you should remove the mock and create a concrete Child object, as you do not want to simulate the behavior of a child, you are trying to achieve it using a mock which removes the functionality of the mock itself.
The simple answer is to use the concrete object in the unit test:
var child = new Child();
child.Bar();
child.Foo();
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 );
}
How should the following method be unit tested?
/// <summary>
/// Entry point for GUI thread.
/// </summary>
public void VerifyDataTypesAsync()
{
Task verificationTask = Task.Factory.StartNew(() =>
{
VerifyDataManagerAsync();
});
}
is it only possible to test via integration testing or is it possible to test that a task was created?
Thanks for your help
You can create a Factory for creating this task and use it through seams. You can use property seam - it is when you set the instance of your factory to a property of an under test class or you can use constructor seam by giving the factory through a constructor. Then you can mock this factory and set it through one of two seams and check does your VerifyDataTypesAsync method call the method of creating your task.
class YourClass
{
public YourClass(ITaskFactory factory)
{}
public void VerifyDataTypesAsync()
{
Task verificationTask = factory.Create(); // you can pass an instance of a delegate as parameter if you need.
}
}
class TasksFactory : IFactory
{
public Task Create()
{
}
}
Then in your test you can create a mock object of IFactory and pass it to the constructor of your class then set mock rules for mock to check if the method Create was called.
If we are talking about NUnit and RhinoMocks it can be looked about this:
var mockRepository = new MockRepository();
var mockObject = mockRepository.CreateMock<IFactory>();
var yourClass = new YourClass(mockObject);
Expect.Call(mockObject.Create);
mockRepository.ReplayAll();
mockObject.VerifyDataTypesAsync()
mockRepository.VerifyAll(); // throw Exception if your VerifyDataTypesAsync method doesn't call Create method of IFactory mock
roughly speaking like this... but it is just one way...
You could wrap the creation of the task in your own Task factory class and verify that it has been used correctly by mocking it in the unit test. For example, create a class like this:
class MyTaskFactory
{
public virtual void CreateTask(Action a)
{
Task.Factory.StartNew(a);
}
}
You supply your objects that need to create tasks with one of these factory objects. In a unit test, you supply a mocked version instead of the actual factory, and see if the CreateTask method has been called.
For more information on mocking, have a look at RhinoMocks or Moq.