c# - Faking a generic method call in C# is not returning the correct object with FakeItEasy
问题描述
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?
解决方案
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);
推荐阅读
- github - Github Enterprise 激活休眠用户
- angular - 如何在自动完成组件中设置滚动条的最大高度
- spring-boot - RabbitMQ DirectMessageListenerContainer 中的消费者 - Cloud Foundry 中的内存影响
- list - Unity3D:使用列表创建网格布局时出错
- php - 在 php 中使用 fb->get() 使用图形 api 获取 facebook 照片
- elasticsearch - 嵌套的 Elasticsearch 查询
- shell - Julia shell 命令如何处理管道?
- java - Java:如何在正在保存的流上即时计算 sha1 摘要?
- yii2 - Yii2 HttpClient:从响应实例访问请求实例
- azure - 从“Get-AzureRmEventHubKey”命令 power-shell 中提取 event-hub Microsoft-azure 的主键