【问题标题】:Mock Async method on Service using Moq使用 Moq 在服务上模拟异步方法
【发布时间】:2017-09-18 10:17:42
【问题描述】:

我正在使用 .Net Core API。我希望在ArtistsController 上对GetArtists 方法进行单元测试。

代码

这是我的控制器代码:

[Route("artists")]
public class ArtistsController : Controller
{
  private readonly IPermissionsService _permissionsService;
  private readonly IArtistsService _artistsService;
  private readonly ILogger<ArtistsController> _logger;

  public ArtistsController(IPermissionsService permissionsService, IArtistsService artistsService, ILogger<ArtistsController> logger)
  {
    _permissionsService = permissionsService ?? throw new ArgumentNullException(nameof(permissionsService));
    _artistsService = artistsService ?? throw new ArgumentNullException(nameof(artistsService));
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  }

  [HttpGet]
  public async Task<IActionResult> GetArtists()
  {
    var permissions = await _permissionsService.GetPermissionsAsync(HttpContext);
    var artists = _artistsService.GetAllArtists(permissions.UserId, permissions.IsAdministrator);
    return Ok( new { artists });
  }
}

这是我正在写的测试方法:

[TestClass]
public class ArtistsControllerTests
{
  private readonly Mock<IPermissionsService> _mockPermissionsService = new Mock<IPermissionsService>();
  private readonly Mock<IArtistsService> _mockArtistsService = new Mock<IArtistsService>();
  private readonly Mock<ILogger<ArtistsController>> _mockLogger = new Mock<ILogger<ArtistsController>>();

  public void Setup()
  {
    _mockArtistsService.Reset();
    _mockPermissionsService
      .Setup(service => service.GetPermissionsAsync(It.IsAny<HttpContext>()))
      .Returns(Task.FromResult(new Permissions { UserId = "112233", IsAdministrator = false }));
    _mockArtistsService.Setup(service => service.GetAllArtists(It.IsAny<string>(), false)).Returns(new ArtistCardDtoCollection());
  }

  [TestMethod]
  public async Task GetArtists_ReturnsOKStatusCode()
  {
    // arrange
    var artistsController = new ArtistsController(_mockPermissionsService.Object, _mockArtistsService.Object, _mockLogger.Object);
    // act
    var getArtistsResult = await artistsController.GetArtists();
    var okResult = getArtistsResult as OkObjectResult;
    // assert
    Assert.IsInstanceOfType(okResult, typeof(OkObjectResult));
  }
}

这是IPermissionsServicePermissions 类。

public interface IPermissionsService
{
  Task<Permissions> GetPermissionsAsync(HttpContext httpContext);
}

public class Permissions
{
  public string UserId { get; set; }
  public bool IsAdministrator { get; set; }
}

当我运行它时,我收到以下错误:

Project.ArtistsControllerTests.GetArtists_ReturnsOKStatusCode 抛出异常: System.NullReferenceException:对象引用未设置为对象的实例。

调试的时候发现var permissions = await _permissionsService.GetPermissionsAsync(HttpContext);返回null

我的嘲笑方式一定有问题:

_mockPermissionsService
    .Setup(service => service.GetPermissionsAsync(It.IsAny<HttpContext>()))

为什么上述方法不起作用?

【问题讨论】:

  • 你能检查哪个变量返回null吗?
  • 不要运行你的测试,把结果放在这里;自己调试。有些东西是空的。
  • 抱歉,我确实尝试过调试@CodeCaster,我忘了添加该信息,抱歉。
  • 添加了一个截屏视频来展示正在发生的事情。
  • @Ciwan 在GetArtists 中放置一个断点,然后单步执行。可能是您没有正确配置其中一个模拟

标签: c# unit-testing asp.net-core moq mstest


【解决方案1】:

ArtistsControllerTests.Setup() 没有被调用,因此在进行测试之前没有设置模拟。

因此,当执行测试时,它们将返回 null。

您的设置代码是正确的,只是没有被调用。

要么将 Setup 方法更改为构造函数

public ArtistsControllerTests() {
    _mockArtistsService.Reset();
    _mockPermissionsService
      .Setup(service => service.GetPermissionsAsync(It.IsAny<HttpContext>()))
      .Returns(Task.FromResult(new Permissions { UserId = "112233", IsAdministrator = false }));
    _mockArtistsService.Setup(service => service.GetAllArtists(It.IsAny<string>(), false)).Returns(new ArtistCardDtoCollection());
}

或者用[TestInitilize]属性修饰方法

[TestInitialize]
public void Setup() {
    _mockArtistsService.Reset();
    _mockPermissionsService
      .Setup(service => service.GetPermissionsAsync(It.IsAny<HttpContext>()))
      .Returns(Task.FromResult(new Permissions { UserId = "112233", IsAdministrator = false }));
    _mockArtistsService.Setup(service => service.GetAllArtists(It.IsAny<string>(), false)).Returns(new ArtistCardDtoCollection());
}

或者只是将排列移动到测试本身

[TestMethod]
public async Task GetArtists_ReturnsOKStatusCode() {
    // arrange
    _mockArtistsService.Reset();
    _mockPermissionsService
      .Setup(service => service.GetPermissionsAsync(It.IsAny<HttpContext>()))
      .Returns(Task.FromResult(new Permissions { UserId = "112233", IsAdministrator = false }));
    _mockArtistsService.Setup(service => service.GetAllArtists(It.IsAny<string>(), false)).Returns(new ArtistCardDtoCollection());
    var artistsController = new ArtistsController(_mockPermissionsService.Object, _mockArtistsService.Object, _mockLogger.Object);
    // act
    var getArtistsResult = await artistsController.GetArtists();
    var okResult = getArtistsResult as OkObjectResult;
    // assert
    Assert.IsInstanceOfType(okResult, typeof(OkObjectResult));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 2010-11-12
    • 2017-04-23
    • 2015-02-13
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    相关资源
    最近更新 更多