Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock Async method on Service using Moq

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?

like image 909
J86 Avatar asked Apr 27 '26 00:04

J86


1 Answers

ArtistsControllerTests.Setup() is not being invoked so the mocks are not being setup before the test is exercised.

Therefore when the test is exercised they will return null.

Your setup code is correct, it just is not getting called.

either change that Setup method to a constructor

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

or adorn the method with [TestInitilize] attribute

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

or just move the arrange into the test itself

[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));
}
like image 59
Nkosi Avatar answered Apr 28 '26 14:04

Nkosi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!