C
C#8mo ago
Natty

How do I properly unit test a post request?

public interface IFacilityService
{
Task<Facility> CreateFacilityAsync(Facility facility);
}
public interface IFacilityService
{
Task<Facility> CreateFacilityAsync(Facility facility);
}
public async Task<Facility> CreateFacilityAsync(Facility facility)
{
_db.Facilities.Add(facility);
await _db.SaveChangesAsync();
return facility;
}
public async Task<Facility> CreateFacilityAsync(Facility facility)
{
_db.Facilities.Add(facility);
await _db.SaveChangesAsync();
return facility;
}
[HttpPost("facility")]
public async Task<IActionResult> CreateFacilityAsync([FromBody] Facility facilityRequest)
{
var createdFacility = await _facilityService.CreateFacilityAsync(facilityRequest);
return Ok(createdFacility);
}
[HttpPost("facility")]
public async Task<IActionResult> CreateFacilityAsync([FromBody] Facility facilityRequest)
{
var createdFacility = await _facilityService.CreateFacilityAsync(facilityRequest);
return Ok(createdFacility);
}
I am using Xunit and Nsubtitute, with EFC, and SQLite db.
11 Replies
Natty
Natty8mo ago
So far I have:
[Fact]
public async Task CreateFacilityAsync_ShouldAddFacilityToDatabase()
{
// Arrange
var newFacility = new Facility { City = "TestCity", Name = "TestName", PhoneNumber = "TestNumber", WebsiteUrl = "TestWebsite" };
var facilityController = new FacilityController(_facilityService);

// Act
await facilityController.CreateFacilityAsync(newFacility);

// Assert
await _facilityService.Received().CreateFacilityAsync(Arg.Any<Facility>());
}
[Fact]
public async Task CreateFacilityAsync_ShouldAddFacilityToDatabase()
{
// Arrange
var newFacility = new Facility { City = "TestCity", Name = "TestName", PhoneNumber = "TestNumber", WebsiteUrl = "TestWebsite" };
var facilityController = new FacilityController(_facilityService);

// Act
await facilityController.CreateFacilityAsync(newFacility);

// Assert
await _facilityService.Received().CreateFacilityAsync(Arg.Any<Facility>());
}
But I don't really understand how to test that a new Facility was successfully added...
Saber
Saber8mo ago
if your mocking the service you can't test that because its a mock which does nothing
Natty
Natty8mo ago
Yeah i am mocking it. So what's the proper way to write a unit test for a post request?
Saber
Saber8mo ago
look into WebApplicationFactory
Natty
Natty8mo ago
Ok. For my Get is this correct tho?
[Fact]
public async Task GetAllFacilitiesAsync_ShouldReturnListOfAllFacilities_WhenDataIsInDatabase()
{
// Arrange
var expectedFacilities = new List<Facility>
{
new() { City = "Houston", Name = "Your Safety", PhoneNumber = "360-555-1234", WebsiteUrl = "www.mycool.com"},
new() { City = "Atlanta", Name = "Big Measures", PhoneNumber = "320-555-1111", WebsiteUrl = "www.bigmeasure.com"},
};

_facilityService.GetAllFacilitiesAsync().Returns(expectedFacilities);
var facilityController = new FacilityController(_facilityService);

// Act
var result = await facilityController.GetAllFacilitiesAsync();

// Assert
var actionResult = Assert.IsType<OkObjectResult>(result);
var model = Assert.IsType<List<Facility>>(actionResult.Value);
Assert.Equal(expectedFacilities.Count, model.Count);
}
[Fact]
public async Task GetAllFacilitiesAsync_ShouldReturnListOfAllFacilities_WhenDataIsInDatabase()
{
// Arrange
var expectedFacilities = new List<Facility>
{
new() { City = "Houston", Name = "Your Safety", PhoneNumber = "360-555-1234", WebsiteUrl = "www.mycool.com"},
new() { City = "Atlanta", Name = "Big Measures", PhoneNumber = "320-555-1111", WebsiteUrl = "www.bigmeasure.com"},
};

_facilityService.GetAllFacilitiesAsync().Returns(expectedFacilities);
var facilityController = new FacilityController(_facilityService);

// Act
var result = await facilityController.GetAllFacilitiesAsync();

// Assert
var actionResult = Assert.IsType<OkObjectResult>(result);
var model = Assert.IsType<List<Facility>>(actionResult.Value);
Assert.Equal(expectedFacilities.Count, model.Count);
}
Saber
Saber8mo ago
looks like a completely worthless test to me
Natty
Natty8mo ago
so this applies to get as well? WebAppFactory mentions integration testing. I think this is correct now:
[Fact]
public async Task CreateFacilityAsync_ShouldSuccessfullyCreateNewFacility()
{
// Arrange
var newFacility = new Facility { City = "TestCity", Name = "TestName", PhoneNumber = "TestNumber", WebsiteUrl = "TestWebsite" };
_facilityService.CreateFacilityAsync(newFacility).Returns(newFacility);

// Act
var result = await _facilityController.CreateFacilityAsync(newFacility);
var okObjectResult = (OkObjectResult)result;

// Assert
Assert.Equal(newFacility, okObjectResult.Value);
Assert.Equal(200, okObjectResult.StatusCode);
}
[Fact]
public async Task CreateFacilityAsync_ShouldSuccessfullyCreateNewFacility()
{
// Arrange
var newFacility = new Facility { City = "TestCity", Name = "TestName", PhoneNumber = "TestNumber", WebsiteUrl = "TestWebsite" };
_facilityService.CreateFacilityAsync(newFacility).Returns(newFacility);

// Act
var result = await _facilityController.CreateFacilityAsync(newFacility);
var okObjectResult = (OkObjectResult)result;

// Assert
Assert.Equal(newFacility, okObjectResult.Value);
Assert.Equal(200, okObjectResult.StatusCode);
}
Saber
Saber8mo ago
yes, however most people will consider this type of testing completely worthless
null
null8mo ago
When unit testing, you should only mock the external dependencies of your system under test. So in your case, _facilityService is the sut and everything else is an external dependency, even the database call. For that matter, any test that contains some kind of I/O, network hop etc. is considered an integration test.
Natty
Natty8mo ago
What is sut? And yeah, I wanted to avoid integration testing here, which I believe this test achieves.
null
null8mo ago
system under test