Reputation: 532
I have this simple example where I would like to test if a method is being invoked on the same class as the calling method:
public class MyClass
{
public void SomeMethod()
{
SomeSubMethod();
}
public virtual void SomeSubMethod()
{
// do a lot of weird stuff
}
}
public class UnitTest1
{
[Fact]
public void Test1()
{
var target = Substitute.ForPartsOf<MyClass>();
target.Configure().SomeSubMethod(); // <---- please just do nothing
target.SomeMethod();
target.Received(1).SomeSubMethod();
}
}
My problem is that SomeSubMethod
is actually invoked in the unit test, and in my real code I would like to avoid that.
A simple work-a-round is to let SomeSubMethod
return something, but now I'm polluting my real code
public class MyClass
{
public void SomeMethod()
{
SomeSubMethod();
}
public virtual int SomeSubMethod()
{
// do a lot of weird stuff
return 0;
}
}
public class UnitTest1
{
[Fact]
public void Test1()
{
var target = Substitute.ForPartsOf<MyClass>();
target.Configure().SomeSubMethod().Returns(0); // <--- Now the real SomeSubMethod won't be invoked
target.SomeMethod();
target.Received(1).SomeSubMethod();
}
}
Is there a way to configure a void method to do nothing?
Yours /peter
Upvotes: 0
Views: 2285
Reputation: 10464
You can use When..Do
syntax to work with void
methods:
public void Test1() {
var target = Substitute.ForPartsOf<MyClass>();
target.When(x => x.SomeSubMethod()).DoNotCallBase(); // <- do not invoke real code
target.SomeMethod();
target.Received(1).SomeSubMethod();
}
Another option, assuming we make SomeMethod
virtual
, is to substitute for all members using the standard Substitute.For<T>
, and opt-in to only call base on the method you want to test.
public void Test2() {
var target = Substitute.For<MyClass>(); // <- substitute all members
target.When(x => x.SomeMethod()).CallBase(); // <- except this one, call the real base implementation for SomeMethod
target.SomeMethod();
target.Received(1).SomeSubMethod();
Assert.Equal(0, target.counter);
}
Documentation links:
Upvotes: 2
Reputation: 139
According to your description, I rewrite the code:
Public class MyClass
{
public int x = 0; // to verify whether the unit test really execute SomeSubMethod()
public void SomeMethod()
{
SomeSubMethod();
}
public virtual void SomeSubMethod()
{
// do a lot of weird stuff
int x = 10;
}
}
And the test is (please note that I use NUnit framework):
[TestFixture]
public class UnitTest1
{
[Test]
public void Test2()
{
var myClass = Substitute.For<MyClass>();
myClass.SomeMethod();
myClass.Received(1).SomeSubMethod();
Assert.That(myClass.x, Is.EqualTo(0));
}
}
Since the target test method SomeSubMethod() is a virtual method, you don't need to mock part the class MyClass.
Is this what you want?
Upvotes: 1