【问题标题】:ContentResult of Web Api controller in Unit Test always returning null单元测试中 Web Api 控制器的 ContentResult 总是返回 null
【发布时间】:2026-02-13 11:45:01
【问题描述】:

我试图在 getMethod(string id) 的单元测试中检查的 ContentResult 总是返回 null。控制器调用的Service返回DTO Model。

我试过了 操作结果为 OkNegotiatedContentResult 操作结果为 OkNegotiatedContentResult

单元测试:

      [TestMethod]
      public void GetUserInformation_ReturnsUserDetails()
        {
            //Arrange
               UserDetails userDetails = new UserDetails();
               mockUserService.Setup(x => 
         x.GetuserInformation(It.IsAny<string> 
          ())).Returns(userDetails);
             //Act
             IHttpActionResult result = 
              userController.GetUserInformation("226");
              var contentResult = result as 
             OkNegotiatedContentResult<UserDetails>;
            //Assert
           //Validate Ok Result
              Assert.IsNotNull(contentResult);//this fails
              Assert.IsNotNull(contentResult.Content);
              Assert.AreEqual("226", contentResult.Content.userID);
              Assert.IsInstanceOfType(result, 
              typeof(OkNegotiatedContentResult<UserDetails>));//this assert works

            }

控制器:

public IHttpActionResult GetUserInformation(string userID)
        {
            if (!string.IsNullOrEmpty(userID))
            {
                var result = _userService.GetUserInformation(userID);
                if (result != null)
                {
                    return Ok(result);
                }
                return InternalServerError();
            }
            else
            {
                return BadRequest("User Not Found");
            }
        }

服务层:

 public UserDetails GetUserInformation(string userID)
        {
            UserDetails userDetails = new UserDetails();
            //business logic
            return userDetails;
        }

ContentNegotiator = '((System.Web.Http.Results.OkNegotiatedContentResult)result).ContentNegotiator' 抛出了“System.InvalidOperationException”类型的异常

Request = '(result as OkNegotiatedContentResult).Request' 引发了“System.InvalidOperationException”类型的异常

【问题讨论】:

  • 其实不是单元测试。您不应该调用控制器来测试服务。控制器中不应该有任何业务逻辑。所有逻辑都应该保留在服务中。
  • 不,如果您没有任何业务逻辑。你不应该有。
  • 您无需模拟即可测试服务。但是通过它的构造函数注入到服务的所有东西都应该被模拟。
  • 试图找到一篇好文章。到处都有人在测试控制器。但这只是浪费时间。你最好专注于服务。关于瘦控制器的文章:adamtibi.net/06-2013/you-should-unit-test-your-controller-not
  • @VladimirSerykh 是否可以对没有接口的服务进行单元测试?

标签: c# unit-testing asp.net-apicontroller


【解决方案1】:

可以有不同的方法来构建 API 应用程序。

我的方法是 API 应该由 3 层构建:

  • 表示层:控制器
  • 业务逻辑:服务
  • 数据层:存储库

控制器和存储库应尽可能薄。所有的逻辑都应该在服务层。在这种情况下,应用程序将是可维护、可扩展和可测试的。

测试示例

使用的包:

  • NUnit
  • NUnit3TestAdapter
  • Moq

你也可以使用:

  • FluentAssertions
  • AutoFixture.NUnit3

服务的测试类示例:

[TestFixture]
public class OrdersServiceTests
{
    private OrdersService _sut;

    private Mock<ICapacityService> _capacityService;

    private Mock<IOrdersRepository> _ordersRepository;

    [SetUp]
    public void Setup()
    {
        // Executed for each test. Mocks are recreated. Tests are not influencing each other.

        _ordersRepository = new Mock<IOrdersRepository>();
        _capacityService = new Mock<ICapacityService>();

        _sut = new OrdersService(_ordersRepository.Object, _capacityService.Object);
    }

    [Test]
    public async Task Should_CheckCapacity_WhenCreatingOrder()
    {
        //// Arrange

        var orderEntity = new OrderEntity
        {
            Id = Guid.NewGuid(),
        };

        //// Act

        await _sut.CreateAsync(orderEntity);

        //// Assert

        _capacityService
            .Verify(
                x => x.CheckCapacity(
                    It.Is<Guid>(g => g.Equals(orderEntity.Id)))),
                Times.Once);
    }
}

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,结果我忘记在 Mock 控制器上调用 Callbase = true

    【讨论】: