Mock Async method on Service using Moq

Viewed 5877

I am working in a .Net Core API. I wish to unit test the GetArtists method on the ArtistsController.

CODE

Here is my controller code:

[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 });
  }
}

And here is the test method I am writing:

[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));
  }
}

Here is the IPermissionsService and the Permissions class.

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

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

When I run that, I get the following error:

Project.ArtistsControllerTests.GetArtists_ReturnsOKStatusCode threw exception: System.NullReferenceException: Object reference not set to an instance of an object.

When debugging, I found out that var permissions = await _permissionsService.GetPermissionsAsync(HttpContext); returns null.

I must have an issue with the way I am mocking that:

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

Why wouldn't the above work?

1 Answers
Related