I'm trying to get better with TDD and implement some unit tests using NUnit for a desk booking application. My Setup is as follows...
[SetUp]
public void Setup()
{
deskBookingRequest = new DeskBookingRequest
{
FirstName = "Alex",
LastName = "Barry",
Email = "[email protected]",
Date = new DateTime(2022, 8, 28)
};
availableDesks = new List<Desk>() { new Desk() };
_databaseService.Setup(x => x.GetDesks(It.IsAny<DateTime>())).Returns(availableDesks);
}
I'm trying to create a scenario in which the .GetDesks
method would return null which would cause the .Save
method to never be called. I figured I could do something like the following (in where the .GetDesks
is called within .BookDesk
...
[Test]
public void ShouldNotSaveDeskIfNoneAreAvailable()
{
//Arrange
availableDesks = null;
//Act
result = _processor.BookDesk(deskBookingRequest);
//Assert
_databaseService.Verify(x => x.Save(It.IsAny<DatabaseSaveBookingRequest>()), Times.Never);
}
but .GetDesks
is still returns a List with one desk object. Would I need to specifically call a new setup method for .GetDesks
or is there a way to achieve what I'm trying to do here?
CodePudding user response:
[Setup]
-annotated methods run before each test method, so it already sets up the _databaseService
with the availableDesks
object. Even when you later null out availableDesks
in the test, the _databaseService
has a reference to the original object.
Do yourself the favour and forgo the use of setup methods. They cause all sorts of aliasing problems like the one you are encountering. Instead, write self-contained test methods like this:
[Test]
public void ShouldNotSaveDeskIfNoneAreAvailable()
{
//Arrange
// ...
databaseService.Setup(x => x.GetDesks(It.IsAny<DateTime>())).Returns(null);
// ...
//Act
result = processor.BookDesk(deskBookingRequest);
//Assert
databaseService.Verify(
x => x.Save(It.IsAny<DatabaseSaveBookingRequest>()),
Times.Never);
}
Don't use class fields, but create object within the test methods.
If you are concerned about code duplication, address that concern like you would in any other code base. If you need inspiration or examples, there's literally an entire book about unit test patterns.