Reputation: 73
I have a base class with a protected method that's being called in a public method in the child class I want to test. I'm failing to find a way to moq the base protected method for easier testing in child class.
public class MyBaseClass
{
protected virtual bool MyMethod(int number)
{
return number == 1;
}
}
public class MyChildClass : MyBaseClass
{
public bool DoSomething(int number)
{
return MyMethod(number);
}
}
[TestFixture]
public class MyChildClassTests
{
[Test]
public void Expected_Returns_False_WhenPassed_1()
{
var myChildClass = new MyChildClass();
// How do I mock MyMethod used in myBaseClass here?
// var mock = new Mock<MyBaseClass>();
// mock.Protected().Setup<bool>("MyMethod", ItExpr.IsAny<int>()).Returns(false);
// The above mock is correct, but it's in a different instance object than myBaseClass
var result = myChildClass.DoSomething();
Assert.AreEqual(false, result);
}
}
I can't change the classes to have a better architecture and I must do the best I can to implement unit test for DoSomething()
, what I did so far is mock and prepare all the data that method uses, but since it's in another class I'd love my MyChildClassTests
to not do all that and just limit to test DoSomething()
.
I've read about partial mocking and a whole lot of other questions and answers and I can't get it to work right.
I appreciate any suggestions!
Edit: Forgot to put public
in all the classes, in my real world case, they are public.
Upvotes: 1
Views: 2179
Reputation: 73
Thanks all for your replies, gathering all I was able to get the actual answer to my use case:
Without changing MyBaseClass
and MyChildClass
:
public class MyBaseClass
{
protected virtual bool MyMethod(int number)
{
return number == 1;
}
}
public class MyChildClass : MyBaseClass
{
public bool DoSomething(int number)
{
return MyMethod(number);
}
}
I was able to mock the protected method and save me a LOT of work and duplicate code (that was in MyBaseClassTests already)
[TestFixture]
public class MyChildClassTests
{
[Test]
public void Expected_Returns_False_WhenPassed_1()
{
var expected = false;
var myChildClass = new Mock<MyChildClass> {CallBase = true};
myChildClass.Protected().Setup<bool>("MyMethod", 1).Returns(expected);
var result = myChildClass.Object.DoSomething(1);
Assert.AreEqual(expected, result);
}
[Test]
public void Expected_Returns_True_WhenPassed_1()
{
var expected = true;
var myChildClass = new Mock<MyChildClass> {CallBase = true};
myChildClass.Protected().Setup<bool>("MyMethod", 1).Returns(expected);
var result = myChildClass.Object.DoSomething(1);
Assert.AreEqual(expected, result);
}
}
Thanks everyone for your help! :)
Upvotes: 0
Reputation: 10680
First of all, ensure your classes are public.
Moq will complain about not being able to proxy into them if they're not.
public class MyBaseClass
{
public virtual bool MyMethod(int number)
{
return number == 1;
}
}
public class MyChildClass : MyBaseClass
{
public bool DoSomething(int number)
{
return MyMethod(number);
}
}
Next, make your base class method public. You won't be able to set it up unless you do.
After that, create a mock of the child object and mock the parent method.
var mockChild = new Mock<MyChildClass>(){CallBase = true};
mockChild.Setup(x => x.MyMethod(It.IsAny<int>())).Returns(false);
Pull your result.... result will return false even though the actual implementation would have returned true with 1 as a parameter.
var result = mockChild.Object.DoSomething(1);
When calling the DoSomething method, you'll actually enter the real implementation of that (put a breakpoint on if you don't believe me!) - but the mocked version of MyMethod will kick in.
Upvotes: 0
Reputation: 347
class MyChildClassTests
{
[Test]
public void Expected_Returns_False_WhenPassed_1()
{
var myChildClass = new FakeChildClass();
var result = myChildClass.DoSomething(1);
Assert.AreEqual(false, result);
}
}
public class FakeChildClass: MyChildClass
{
protected override bool MyMethod(int number)
{
return number == 1;
}
}
Upvotes: 0