You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用XUnit和Moq测试GetRefusalPdf接口方法?

完善ASP.NET Core Post接口的XUnit+Moq测试用例

首先明确待测试接口的核心逻辑:

  • 入参refusal为null时返回406状态码
  • 入参有效时,先记录API请求日志,再调用服务生成PDF流,最后返回带指定文件名的PDF文件

测试前的准备工作

测试类需要模拟控制器的两个依赖项ILoggingFactory和IDispatchRefusalService,同时为控制器配置HttpContext(日志方法需要用到该对象)。

using Xunit;
using Moq;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System;

public class DispatchRefusalControllerTests
{
    private readonly Mock<ILoggingFactory> _mockLoggingFactory;
    private readonly Mock<IDispatchRefusalService> _mockDispatchService;
    private readonly DispatchRefusalController _controller;

    public DispatchRefusalControllerTests()
    {
        // 初始化Mock依赖
        _mockLoggingFactory = new Mock<ILoggingFactory>();
        _mockDispatchService = new Mock<IDispatchRefusalService>();
        
        // 创建控制器实例并注入Mock依赖
        _controller = new DispatchRefusalController(_mockLoggingFactory.Object, _mockDispatchService.Object);
        
        // 配置控制器的HttpContext(满足日志方法的调用要求)
        _controller.ControllerContext.HttpContext = new DefaultHttpContext();
    }
}

测试场景1:入参为null时返回406状态码

[Fact]
public async Task GetRefusalPdf_Returns406Status_WhenRefusalIsNull()
{
    // 执行接口方法
    var result = await _controller.GetRefusalPdf(null);
    
    // 断言返回结果的类型和状态码
    var statusCodeResult = Assert.IsType<StatusCodeResult>(result);
    Assert.Equal(StatusCodes.Status406NotAcceptable, statusCodeResult.StatusCode);
    
    // 验证依赖方法未被触发(入参为空直接返回,无需执行后续逻辑)
    _mockLoggingFactory.Verify(f => f.LogApiRequests(It.IsAny<HttpContext>()), Times.Never);
    _mockDispatchService.Verify(s => s.GenerateEtsRefusalFormAsync(It.IsAny<DispatchRefusal>()), Times.Never);
}

测试场景2:入参有效时返回正确的PDF文件结果

[Fact]
public async Task GetRefusalPdf_ReturnsValidFileResult_WhenRefusalIsValid()
{
    // 1. 准备测试数据
    var testRefusal = new DispatchRefusal
    {
        PatientName = "John Doe",
        RefusalDateTime = new DateTime(2024, 5, 20)
    };
    var testPdfStream = new MemoryStream();
    var expectedFileName = $"Refusal-{testRefusal.PatientName}-{testRefusal.RefusalDateTime.ToString("yy-MM-dd")}.pdf";
    
    // 2. 模拟PDF生成服务的返回值
    _mockDispatchService.Setup(s => s.GenerateEtsRefusalFormAsync(testRefusal))
                        .ReturnsAsync(testPdfStream);
    
    // 3. 执行接口方法
    var result = await _controller.GetRefusalPdf(testRefusal);
    
    // 4. 断言返回结果的正确性
    var fileResult = Assert.IsType<FileStreamResult>(result);
    Assert.Equal("application/pdf", fileResult.ContentType);
    Assert.Equal(expectedFileName, fileResult.FileDownloadName);
    Assert.Same(testPdfStream, fileResult.FileStream);
    
    // 5. 验证依赖方法的调用情况
    _mockLoggingFactory.Verify(f => f.LogApiRequests(_controller.HttpContext), Times.Once);
    _mockDispatchService.Verify(s => s.GenerateEtsRefusalFormAsync(testRefusal), Times.Once);
}

关键测试点说明

  • 依赖验证:通过Moq的Verify方法确保日志服务和PDF生成服务被正确调用(调用次数、传入参数匹配)
  • 结果断言:不仅验证返回结果的类型,还要检查ContentType、文件名、流对象的一致性
  • 边界场景覆盖:覆盖入参为null的异常分支,确保接口的错误处理逻辑符合预期

内容的提问来源于stack exchange,提问作者user14525299

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:39:55