我正在使用 ASP.NET Core 7.0,并且有一个 Web API。 我有一个简单的控制器,如下所示:
[ApiController]
[Route("api/payment")]
public class PaymentController : ControllerBase
{
private readonly ILogger logger;
public PaymentController(ILogger logger)
{
this.logger = logger;
}
[HttpPost("createPayment")]
public Task<MyResponse> CreatePayment([FromBody] PaymentInfo paymentInfo)
{
PaymentAction action = CreatePaymentAction(paymentInfo);
Task<MyResponse> payload = action.Execute();
return payload;
}
}
PaymentInfo
是包含有关特定付款的详细信息的类。
CreatePaymentAction
是一个辅助方法,用于创建 PaymentAction
类型的对象,在该对象中,有 Execute
方法将付款详细信息插入数据库。
MyResponse
是我创建的用于保存响应数据的类。
现在我想测试我的控制器,但我真的不想将数据插入到我的数据库中,所以我想模拟它。
我尝试了这样的事情,使用最小起订量:
[Fact]
public async Task CreatePaymentReturnsSuccessCode()
{
// Arrange
PaymentInfo paymentInfo = CreatePaymentInfo();
StringContent content = new StringContent(JsonConvert.SerializeObject(paymentInfo), Encoding.UTF8, "application/json");
Mock<PaymentAction> mockPaymentAction = new Mock<PaymentAction>();
mockPaymentAction.Setup(m => m.Execute()).Returns(Task.FromResult(new MyResponse() { Message = "Success", Code = "200", Status = "Ok" }));
// Assert
HttpResponseMessage response = await client.PostAsync("api/payment/createPayment", content);
MyResponse responseContent = await response.Content.ReadAsAsync<MyResponse>();
// Act
Assert.Equal("Success", responseContent.Message);
Assert.Null(responseContent.Exception);
Assert.Equal("Ok", responseContent.Status);
}
当我尝试运行测试时,它实际上将真实数据插入数据库并且不使用模拟对象。 有人可以帮我找出原因以及如何解决这个问题吗?
您不能只在单元测试中定义测试替身并期望它替换真正的依赖项。您需要以某种方式将其传递给被测系统 (SUT)。
由于您似乎使用 WebApplicationFactory 自托管 SUT,因此您可以使用其 ConfigureWebHost 方法来覆盖注入的依赖项。 这是一个例子。
如果您希望在单元测试中覆盖
PaymentAction.Execute
的行为,则需要以某种方式注入 PaymentAction
从 PaymentController
接收的 CreatePaymentAction
对象。标准构造函数注入可能是最简单的方法。