It came to my attention lately that you can unit test abstract base classes using Moq rather than creating a dummy class in test that implements the abstract base class. See How to use moq to test a concrete method in an abstract class? E.g. you can do:
public abstract class MyAbstractClass
{
public virtual void MyMethod()
{
// ...
}
}
[Test]
public void MyMethodTest()
{
// Arrange
Mock<MyAbstractClass> mock = new Mock<MyAbstractClass>() { CallBase = true };
// Act
mock.Object.MyMethod();
// Assert
// ...
}
Now I was wondering if there was a similar technique to allow me to test protected members without having to create a wrapper class. I.e. how do you test this method:
public class MyClassWithProtectedMethod
{
protected void MyProtectedMethod()
{
}
}
I’m aware of the Moq.Protected namespace, however as far as I can see it only allows you to setup expectations with e.g.
mock.Protected().Setup("MyProtectedMethod").Verifiable();
I’m also aware that the obvious answer here is “don’t test protected methods, only test public methods”, however that’s another debate! I just want to know if this is possible using Moq.
Update: below is how I would test this normally:
public class MyClassWithProtectedMethodTester : MyClassWithProtectedMethod
{
public void MyProtectedMethod()
{
base.MyProtectedMethod();
}
}
Thanks in advance.
For starters, there’s no point in unit testing an abstract method. There’s no implementation! You may want to unit test an impure abstract class, verifying that the abstract method was called:
Note that I set CallBase to turn this into a partial mock, in case Do was virtual. Otherwise Moq would have replaced the implementation of the Do method.
Using Protected() you could verify that a protected method was called in a similar manner.
When you create a mock with Moq or another library, the whole point is overriding implementation. Testing a protected method involves exposing existing implementation. That’s not what Moq is designed to do. Protected() just gives you access (presumably through reflection, since it’s string-based) to override protected members.
Either write a test descendant class with a method that calls your protected method, or use reflection in the unit test to call the protected method.
Or, better yet, don’t test protected methods directly.