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

单元测试控制器报错:使用MS Testing测试控制器时出现异常

问题排查与修复方案

先梳理测试代码及相关逻辑中的核心问题,再给出针对性修复方案:

1. 控制器实例化语法错误

测试代码里的控制器初始化逻辑完全错误:

_Controller = ProductCatsController(_Controller.Object);

正确做法是传入已Setup好的_categoryRepository.Object,以及需要Mock的IMapper实例(控制器构造函数要求两个参数),你需要先创建Mock<IMapper>实例,再传入控制器。

2. 未Setup AutoMapper映射逻辑

控制器CreateCategory方法两次调用_mapper.Map:

  • 将CreateCatDto映射为ProductCat
  • 将ProductCat映射为CategoryDto
    若测试未对这两个映射做Setup,Mapper会返回null,后续调用CatForReturn.Id时会触发NullReferenceException。

3. 测试方法标记async但无await操作

测试方法声明为public async Task PostDataReturnOk(),但体内没有任何await调用,会导致测试被当作同步执行,引发不可预期行为。如果AddCat是同步方法,直接移除async,改为public void PostDataReturnOk();如果是异步方法,需确保用await并返回Task。

4. 未调用待测试的CreateCategory方法

当前测试仅Setup了Repository、实例化了控制器,但完全没有调用目标测试方法,未达到测试目的。

5. 未处理[Authorize]属性

控制器方法带有[Authorize(Roles = "Admin")],默认测试时会返回401 Unauthorized,需在测试中模拟用户授权,或绕过授权验证。


修正后的完整测试代码示例

假设使用Moq框架,修正后的测试代码如下:

// 类级别声明Mock实例
private Mock<IProCatRepository> _categoryRepository;
private Mock<IMapper> _mapper;
private ProductCatsController _controller;
private Fixture _fixture;

[TestInitialize] // MS Test初始化方法
public void Setup()
{
    _fixture = new Fixture();
    _categoryRepository = new Mock<IProCatRepository>();
    _mapper = new Mock<IMapper>();
    // 初始化控制器
    _controller = new ProductCatsController(_categoryRepository.Object, _mapper.Object);
    
    // 模拟Admin角色授权
    var user = new ClaimsPrincipal(new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.Role, "Admin")
    }));
    _controller.ControllerContext = new ControllerContext
    {
        HttpContext = new DefaultHttpContext { User = user }
    };
}

[TestMethod]
public void PostDataReturnCreatedResult()
{
    // 1. 准备测试数据
    var createCatDto = _fixture.Create<CreateCatDto>();
    var productCat = _fixture.Create<ProductCat>();
    var categoryDto = _fixture.Create<CategoryDto>();

    // 2. Setup Mapper映射
    _mapper.Setup(m => m.Map<ProductCat>(createCatDto)).Returns(productCat);
    _mapper.Setup(m => m.Map<CategoryDto>(productCat)).Returns(categoryDto);

    // 3. Setup Repository的AddCat方法
    _categoryRepository.Setup(re => re.AddCat(It.IsAny<ProductCat>())).Returns(productCat);

    // 4. 调用待测试方法
    var result = _controller.CreateCategory(createCatDto);

    // 5. 断言结果符合预期
    var createdAtRouteResult = result.Result as CreatedAtRouteResult;
    Assert.IsNotNull(createdAtRouteResult);
    Assert.AreEqual("GetCat", createdAtRouteResult.RouteName);
    Assert.AreEqual(categoryDto.Id, (createdAtRouteResult.RouteValues["id"] as int?)?.Value);
    Assert.AreEqual(categoryDto, createdAtRouteResult.Value);

    // 验证依赖方法是否被正确调用
    _categoryRepository.Verify(re => re.AddCat(productCat), Times.Once);
    _mapper.Verify(m => m.Map<ProductCat>(createCatDto), Times.Once);
    _mapper.Verify(m => m.Map<CategoryDto>(productCat), Times.Once);
}

额外说明

  • 若AddCat是异步方法(返回Task<ProductCat>),需将测试方法改为async Task,调用时用await,同时Setup时用ReturnsAsync:
    _categoryRepository.Setup(re => re.AddCat(It.IsAny<ProductCat>())).ReturnsAsync(productCat);
    var result = await _controller.CreateCategory(createCatDto);
    
  • 确保已安装必要NuGet包:Moq、AutoMapper、AutoFixture(若使用)、Microsoft.AspNetCore.Mvc.Testing(若需完整测试上下文)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:25:32