I have a TestFixture marked class which is Unit testing the functionality of a class named 'HideCurrentTitleBarMessageTask'.
In this class I use a substitute to mock an interface in the [Setup] method, and in SOME tests in the test class I setup a return result from one of that mocked interfaces members.
[TestFixture]
public class TestClass_A {
private ITitleBarMessageModel model;
private ITitleBarMessage message;
private HideCurrentTitleBarMessageTask task;
private bool taskCompleteFired;
[SetUp]
public void SetUp() {
taskCompleteFired = false;
model = Substitute.For<ITitleBarMessageModel>();
message = Substitute.For<ITitleBarMessage>();
//model.currentlyDisplayedMessage = null;
task = new HideCurrentTitleBarMessageTask();
task.Init(model);
task.Completed += (t) => { taskCompleteFired = true; };
}
[Test]
public void Test_A() {
task.Execute();
Assert.That(taskCompleteFired, Is.True);
}
[Test]
public void Test_B() {
model.currentlyDisplayedMessage.Returns(message);
task.Execute();
message.Received(1).Hide();
Assert.That(taskCompleteFired, Is.False);
}
}
HideCurrentTitleBarMessageTask's Execute function looks like this
public override void Execute() {
if (model.currentlyDisplayedMessage != null) {
//Some irrelevant stuff
} else {
Completed(this);
}
}
Notice that only in Test_B, do I setup a return value with model.currentlyDisplayedMessage.
If I breakpoint in line 1 of Test_A, I see in the debugger that model.currentlyDisplayedMessage is not null, but in fact assigned. When it shouldn't be. Even though presumably, the method SetUp was called prior, and the line
model = Substitute.For<ITitleBarMessageModel>();
was executed, effectively reassigning a new mocked instance to the model. This causes Test_A to fail.
Now, notice the commented out line
//model.curentlyDisplayedMessage = null;
in the SetUp method. Uncommenting this, fixes the issue by explicitly setting the reference in model to null. (I'm also assuming the same result could be achieved in a [TearDown] marked method).
Does NUnit not wipe out the TestClass and start from scratch in between tests?
If not, can anybody tell me why my call to
model = Substitute.For<ITitleBarMessageModel>();
in the SetUp() method hasn't provided me with a clean mocked instance of the model, to start my test with?
The fixture is created once for all of the tests in that fixture. For a given fixture class, a FixtureSetup method is run once for all of the tests in a fixture, and a Setup method is run once for each test.
The [TestFixture] attribute denotes a class that contains unit tests. The [Test] attribute indicates a method is a test method.
This attribute is to identify methods that are called once prior to executing any of the tests in a fixture. It may appear on methods of a TestFixture or a SetUpFixture. OneTimeSetUp methods may be either static or instance methods and you may define more than one of them in a fixture.
In NUnit we have Test Fixtures containing Tests. A Test Fixture is the class that contain the tests we want to run. We typically write one test fixture for each class we want to test. As a convention we name the test fixture <Class to be tested>Tests.
No, NUnit does not create a new instance of your fixture class for each test case. A single instance is created and then reused for each test. This is different from some other test frameworks but it is how NUnit has always worked (since 2000).
The implication is that you have to be careful how you use the object state. 1. Use as little state as possible. 2. Use SetUp to initialize and TearDown to clean up.
Per @David's comment... NSubstitute will automatically substitute for members that return interfaces. See Recursive mocks. I think this explains why model.currentlyDisplayedMessage is initialised for a freshly substituted model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With