How to Moq a Portion of a Class and Test the Other Part of it
Posted on: 2015-02-20
Unit testing against an interface is something that we do often with the help of Mock's framework. This allow to not execute code that we are not testing - to concentrate on the real code to test. However, what happen if you want to test a concrete class and only test a portion of it - you want to mock the other inherited method of that interface. Let's say that that we have a simple class that inherit an interface with two methods. If one method call the other and that we do not want to test this other method than we want to mock. For example, if you have one method that does some logic, call the second method that is slow because it goes into the file system, the web or has other logic that you do not want to tests, than you are in this scenario. Here is some code that we will use to demonstrate how to test only a portion of a class whilst having the rest Moq.
public interface IMyInterface { void TransformationA(); void TransformationB(); }
public class MyConcreteImplementation : IMyInterface { public MyConcreteImplementation(int counter) { Counter = counter; }
public int Counter { get; set; } public void TransformationA() { Counter++; TransformationB(); Counter++; }
public void TransformationB() { Thread.Sleep(25000); } }
We have a class named MyConcreteImplementation that implements the IMyInterface. The purpose of the test would me to test the method TransformationA. This mean that we want to Mock TransformationB. This is problematic because we cannot mock the whole concrete instance of MyConcreteImplementation because the test will be against the mock and not the instance. However, we can mock the method we want to test to execute the real concrete implementation and keep the mock on the other method. The unit test should looks like:
[TestClass] public class TransformationATest { [TestMethod] public void MyTest() { //Arrange var whatWeWantToTest = new MyConcreteImplementation(100); var mock = new Mock<IMyInterface>(); mock.Setup(d => d.TransformationA()).Callback(whatWeWantToTest.TransformationA); // -- We do nothing for B --
// Act mock.Object.TransformationA();
//Assert Assert.AreEqual(102, whatWeWantToTest.Counter);
} }
The code is creating a mock and use the mocking's framework to do a callback on the real implementation that we want to test. The test occurs on the mock which act as a proxy for the concrete implementation. This way, the mocking framework is acting as it should for all methods excepted the one we want to test.
You can find this example on GitHub : https://github.com/MrDesjardins/MockingPortionOfCode. It uses Moq as Mocking's framework but any others would do the same.
If you want to do the samething with a method that return a result, instead of using the Callback
method, use the Returns
method of your mocking framework.
Edit (2016-08-09): It's also possible to do it pretty easily if the method tested is virtual
. Here is a real example where we mock a concrete class by supplying all parameters like we would do normally. The setup take out the method you do not want to execute of the tested class. This is the one the need to be public
and virtual
. The assertion can check that method to see if it's been touched.
// Arrange var mock = new Mock<PortefolioAccessor>(this.runningContest.Object, this.unitOfWork.Object, this.UnitOfWorkDapper.Object, this.portefolioRepository.Object, this.cache.Object); mock.Setup(d => d.SetPortefolioInCache(It.IsAny<Portefolio>(), false));
// Act mock.Object.SaveInterDayStatistics(contest);
// Assert mock.Verify(d=>d.SetPortefolioInCache(It.IsAny<Portefolio>(), false), Times.Exactly(1));