ASP.NET核心单元测试在测试控制器问题响应时引发Null异常



我正在为我的项目创建基本的单元测试。出于某种原因,在测试我得到ControllerBase.Problem(String, String, Nullable<Int32>, String, String)响应时,我一直得到一个NullReferenceException。我确信这个问题与控制器没有实际运行不一致,因为当控制器运行时,它似乎表现得非常好。

控制器:

[HttpGet("{id}")]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetPatient([GuidNotEmpty] Guid id)
{
Patient patient = null;
patient = _patientDbService.FindPatient(id);
if (patient == null) {
return Problem("Patient not found.", string.Empty, StatusCodes.Status404NotFound,
"An error occurred.", "https://tools.ietf.org/html/rfc7231#section-6.5.1");
}
return Ok(patient);
}

测试:

[Fact]
public void TestGetPatientFromIdPatientNotFound()
{
// Act
IActionResult result = _patientController.GetPatient(Guid.NewGuid());
// Assert
Assert.IsType<ObjectResult>(result);
Assert.NotNull(((ObjectResult)result).Value);
Assert.IsType<ProblemDetails>(((ObjectResult)result).Value);
Assert.Equal(((ObjectResult)result).StatusCode, StatusCodes.Status404NotFound);
}

结果:

X PatientServiceTest.PatientServiceUnitTest.TestGetPatientFromIdPatientNotFound [1ms]
Error Message:
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
at Microsoft.AspNetCore.Mvc.ControllerBase.Problem(String detail, String instance, Nullable`1 statusCode, String title, String type)
at PatientService.Controllers.PatientController.GetPatient(Guid id) in /home/surafel/coding/microservices-dev/c#/PatientService/Controllers/PatientController.cs:line 43
at PatientServiceTest.PatientServiceUnitTest.TestGetPatientFromIdPatientNotFound() in /home/surafel/coding/microservices-dev/c#/PatientServiceTest/PatientServiceUnitTest.cs:line 69

正如Aluan Haddad在评论中指出的,Problem()调用ProblemDetailsFactory来创建由服务管理器提供的ProblemDetails对象。服务管理器仅在应用程序正在运行时工作:https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ControllerBase.cs#L194

可以设置ControllerBase.ProblemDetailsFactory变量,所以我创建了一个mockProblemDetailsFactory实例,并将控制器工厂设置为我的mock实例。这似乎使它发挥了作用。

实物模型:

public class MockProblemDetailsFactory : ProblemDetailsFactory
{
public MockProblemDetailsFactory()
{
}
public override ProblemDetails CreateProblemDetails(HttpContext httpContext,
int? statusCode = default, string title = default,
string type = default, string detail = default, string instance = default)
{
return new ProblemDetails() {
Detail = detail,
Instance = instance,
Status = statusCode,
Title = title,
Type = type,
};
}
public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext,
ModelStateDictionary modelStateDictionary, int? statusCode = default,
string title = default, string type = default, string detail = default,
string instance = default)
{
return new ValidationProblemDetails(new Dictionary<string, string[]>()) {
Detail = detail,
Instance = instance,
Status = statusCode,
Title = title,
Type = type,
};
}
}

我在这个单元测试的设置中添加了这一行,它解决了问题。

_patientController.ProblemDetailsFactory = new MockProblemDetailsFactory();

最新更新