如何模拟对外部服务的调用

问题描述 投票:0回答:1

我正在使用 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);
}

当我尝试运行测试时,它实际上将真实数据插入数据库并且不使用模拟对象。 有人可以帮我找出原因以及如何解决这个问题吗?

c# asp.net-core-webapi moq asp.net-core-7.0
1个回答
0
投票

不能只在单元测试中定义测试替身并期望它替换真正的依赖项。您需要以某种方式将其传递给被测系统 (SUT)。

由于您似乎使用 WebApplicationFactory 自托管 SUT,因此您可以使用其 ConfigureWebHost 方法来覆盖注入的依赖项。 这是一个例子

如果您希望在单元测试中覆盖

PaymentAction.Execute
的行为,则需要以某种方式注入
PaymentAction
PaymentController
接收的
CreatePaymentAction
对象。标准构造函数注入可能是最简单的方法。

© www.soinside.com 2019 - 2024. All rights reserved.