I have a piece of code that I may not be able to change. Ideally I’d move the Publish method into another class. Mocking would become a trivial operation and I’d be good. Here’s a simplified example.
public class Entity
{
private IController _controller;
// Omitted: Constructor where IController is assigned
public virtual int Process()
{
return Publish(_controller.DoSomeStuff());
}
public virtual int Publish(int val)
{
Console.WriteLine(val); // This is actually a call to an external system.
return val;
}
}
What I want to do is call the real Process method and a mocked Publish method. The value of _controller will be mocked as well.
I tried using moq and doing:
var mock = new Mock<IController>();
mock.Setup(m => m.DoSomeStuff()).Returns(11);
var mock2 = new Mock<Entity_Accessor>();
mock2.CallBase = true;
mock2.Setup(a => a.Publish(It.IsAny<int>())).Returns(999);
mock2.Object._controller = mock.Object;
int result = mock2.Object.Process();
Assert.AreEqual(999, result);
When I run this test, the value of 11 is returned instead of 999. If I remove mock2.CallBase = true, the entire class is mocked which returns default values for every function.
Is it possible to mock just the Publish method in this case while retaining the original implementation of Process?
Is it possible to achieve the above with a different mocking framework that isn’t Typemock or Justmock (not sure if the customer will foot the bill for multiple copies of a mocking tool)?
Thank you!
If you are trying to test the functionality of the
Processmethod you should not be using a mock, you should be using a real instance of the class and mocking theIControllerinterface and mockDoSomeStuffto return an expected value and then verify thatProcesscorrectly handles that value.If you are simply trying to mock your
Entityclass, then there is no need to mock theIController. Just mock your methods on theEntityclass and have them return what you want.Update:
You shouldn’t need to mock part of the class you are testing. Maybe you should be passing in a reference to the external system so that you can mock it. Unless the code in Publish is the responsible party for directly calling the external system. This would be the recommended approach. However if the Publish method is responsible for calling the external system directly, then you need to take a different approach and do integration testing instead.
Integration testing usually does not run fast in comparison to unit tests, and it requires that all system interacting be up and running. It also means that in most cases you won’t be mocking things. This is the nature of the beast and I would highly recommend that you not circumvent a process such as this.