Reputation: 4119
I have this method I need to test
public async Task<IActionResult> Completed(string nprUserId, [FromBody] DateRangeDto model)
{
var result = await _geAppService.Completed<ExpandoObject>(nprUserId, model.StartDate, model.EndDate);
var r = result as OperationResult;
if (r == null)
{
// There is no error. Return JSON
return Json(result, camelCaseOption);
}
else
{
// An error occurred. Return a 404 and include the error message
return NotFound(r.ErrorMessage);
}
}
This is my test
[Fact]
[Trait("Controller", "Completed")]
public async Task Completed_WhenRIsNotNull_ReturnNotFoundWithMessage()
{
//arrange
string nprUserId = string.Empty;
var model = CreateRandomDateRangeDto();
OperationResult r = CreateRandomOperationResult();
var startDate = DateTime.Now;
var endDate = DateTime.Now;
//I tried this
A.CallTo(nprAppService)
.Where(call => call.Method.Name == "Completed")
.WithReturnType<OperationResult>()
.Returns(r);
//I tried this as well
A.CallTo(() => nprAppService.Completed<ExpandoObject>(nprUserId, startDate, endDate))
.Returns(r);
//act
var result = await controller.Completed(nprUserId, model);
// Assert
A.CallTo(() => nprAppService.Completed<ExpandoObject>(nprUserId, startDate, endDate))
.MustHaveHappened();
result.Should().BeOfType<NotFoundObjectResult>()
.Subject.Value.Should().BeOfType<string>();
}
When the sut: controller gets called, the Complete generic method returns an object instead of an OperationResult.
How can I solve this issue?
Upvotes: 1
Views: 1042
Reputation: 76
Assuming CreateRandomDateRangeDto
returns the model with StartDate
and EndDate
set to DateTime.Now
,
Your test should be using model.StartDate
and model.EndDate
instead of startDate
, and endDate
in the test method. because their values will be different.
[Fact]
[Trait("Controller", "Completed")]
public async Task Completed_WhenRIsNotNull_ReturnNotFoundWithMessage()
{
//arrange
string nprUserId = string.Empty;
var model = CreateRandomDateRangeDto();
OperationResult r = CreateRandomOperationResult();
A.CallTo(() => nprAppService.Completed<ExpandoObject>(nprUserId, model.StartDate, model.EndDate))
.Returns(r);
//act
var result = await controller.Completed(nprUserId, model);
// Assert
A.CallTo(() => nprAppService.Completed<ExpandoObject>(nprUserId, model.StartDate, model.EndDate))
.MustHaveHappened();
result.Should().BeOfType<NotFoundObjectResult>()
.Subject.Value.Should().BeOfType<string>();
}
Update: Further explanation
For the first approach of configuring through passing the fake object, the return type should include Task
.
A.CallTo(nprAppService)
.Where(call => call.Method.Name == "Completed")
.WithReturnType<Task<OperationResult>>()
.Returns(r)
The second approach requires the exact value/object in order to return the specified object. That's why the test only works with model.EndDate
and model.StartDate
If you didn't care about the start and end date values matching, you can...
A.CallTo(() => nprAppService.Completed<ExpandoObject>(nprUserId, A<DateTime>._, A<DateTime>._))
.Returns(r);
Upvotes: 3