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

Moq.MockException测试失败:期望IMapper.Map调用1次却未执行

问题描述

Message: Moq.MockException:

Expected invocation on the mock once, but was 0 times: m => m.Map(AnnotationMasterRequest)

Performed invocations:MockIMapper:1 (m):

No invocations performed.

服务方法代码

public async Task<ServiceResponse<AnnotationMasterResponse>> CreateAnnotation(AnnotationMasterRequest annotationMasterRequest)
{
    return await serviceResponseExceptionHandler.HandleAsync(async () =>
    {
        var annotationMaster = _mapper.Map<AnnotationMaster>(annotationMasterRequest);
        annotationMaster.AnnotationMasterId = Guid.NewGuid();

        var responseResult = await base.Insert(annotationMaster);
        return responseResult.DataResult;
    }, annotationMasterRequest);
}

测试用例代码

public class AnnotationMasterServiceTests
{
    private readonly Mock<IUnitOfWork> _unitOfWorkMock;
    private readonly Mock<IMapper> _mapperMock;
    private readonly Mock<IServiceResponseExceptionHandler> _exceptionHandlerMock;
    private readonly AnnotationMasterService _service;

    public AnnotationMasterServiceTests()
    {
        _unitOfWorkMock = new Mock<IUnitOfWork>();
        _mapperMock = new Mock<IMapper>();
        _exceptionHandlerMock = new Mock<IServiceResponseExceptionHandler>();
        _service = new AnnotationMasterService(
            _unitOfWorkMock.Object,
            _mapperMock.Object,
            _exceptionHandlerMock.Object);
    }

    [Fact]
    public async Task CreateAnnotation_ShouldReturnSuccess_WhenValidRequest()
    {
        // Arrange
        var request = new AnnotationMasterRequest 
        {
            AnnotationMasterName = "test"
        };
        var annotationMaster = new AnnotationMaster();

        var annotationMasterResponse = new AnnotationMasterResponse { /* populate fields */ };

        // Create a mock ServiceResponse that returns a valid response, but we don't need to access internal properties.
        var serviceResponse = new ServiceResponse<AnnotationMasterResponse>
        {
            // Leave the internal properties (DataResult, Success, Message) as they are
            // Your test doesn't need to access them directly; we assume the ServiceResponse is set up correctly
        };

        _mapperMock.Setup(m => m.Map<AnnotationMaster>(request)).Returns(annotationMaster);

        _exceptionHandlerMock.Setup(e => e.HandleAsync(It.IsAny<Func<Task<AnnotationMasterResponse>>>(), request)).ReturnsAsync(serviceResponse);

        // Act
        var result = await _service.CreateAnnotation(request);

        // Assert
        Assert.NotNull(result);
        Assert.Equal(serviceResponse.DataResult, result.DataResult);
        _mapperMock.Verify(m => m.Map<AnnotationMaster>(request), Times.Once);
    }
}

Mapper代码

public class AnnotationMasterMapper : Profile
{
    public AnnotationMasterMapper()
    {
        CreateMap<AnnotationMasterRequest, AnnotationMaster>();
        CreateMap<AnnotationMaster, AnnotationMasterResponse>();

        CreateMap<Annotation, AnnotationResponse>();
    }
}
问题原因

测试中对_exceptionHandlerMock的配置直接返回了预设的serviceResponse,完全没有执行传入的业务逻辑委托(也就是服务方法里包含_mapper.Map的那段代码),导致_mapper.Map从未被调用,触发了Moq的验证失败。

解决方案

1. 让ExceptionHandler的Mock执行传入的业务委托

修改_exceptionHandlerMock的Setup,使其实际执行传入的委托,模拟真实的ExceptionHandler行为:

// 替换原来的ExceptionHandler Setup
_exceptionHandlerMock.Setup(e => e.HandleAsync(It.IsAny<Func<Task<AnnotationMasterResponse>>>(), It.IsAny<AnnotationMasterRequest>()))
    .ReturnsAsync(async (Func<Task<AnnotationMasterResponse>> func, AnnotationMasterRequest req) => 
    {
        // 执行传入的业务逻辑委托
        var responseData = await func();
        // 包装成ServiceResponse返回(如果需要模拟异常处理的其他逻辑,也可以在这里添加)
        return new ServiceResponse<AnnotationMasterResponse> { DataResult = responseData };
    });

2. 补充Mock基类Insert方法的行为

因为执行业务委托时会调用base.Insert,所以需要给_unitOfWorkMock补充对应的Setup(假设基类的Insert方法依赖IUnitOfWork):

// Arrange阶段添加:
var insertedResponse = new ServiceResponse<AnnotationMasterResponse>
{
    DataResult = annotationMasterResponse // 这里用你预设的AnnotationMasterResponse
};
// 假设基类Insert最终调用_unitOfWork的某个方法,比如InsertAsync
_unitOfWorkMock.Setup(u => u.InsertAsync(It.IsAny<AnnotationMaster>()))
    .ReturnsAsync(insertedResponse);

3. 调整Mapper的验证逻辑(可选)

如果不想严格匹配传入的request对象,可以用It.IsAny<AnnotationMasterRequest>()来放宽验证条件,避免因为对象引用不匹配导致的验证失败:

_mapperMock.Verify(m => m.Map<AnnotationMaster>(It.IsAny<AnnotationMasterRequest>()), Times.Once);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:05:02