2

I'm trying to learn unit testing in xUnit for ASP.NET Core projects. In order to achieve it, I have created simple ASP.NET Core project to perform tests on it. However I cannot get 100% cover of tests due to wrong testing an exception that's being caught inside controller method.

Here is my controller method I'm testing:

        [HttpGet]
        public async Task<IEnumerable<User>> GetUsers()
        {
            try
            {
                var users = await _repository.User.GetAllUsersAsync();
                return users;
            }
            catch (Exception e)
            {
                _logger.LogError($"Error in GetUsers: {e}");
                return null;
            }
        }

And here is my unit test method in xUnit:

        [Fact]
        public async Task GetUsers_WhenCalled_ReturnsCorrectAmountOfUsers()
        {
            //Arrange
            var mockRepo = new Mock<IRepositoryWrapper>();
            mockRepo.Setup(repo => repo.User.GetAllUsersAsync())
                .ReturnsAsync(GetTestUsers());
            var controller = new UsersController(mockRepo.Object, _logger, _service);

            //Act
            var result = await controller.GetUsers();

            //Assert
            var model = Assert.IsAssignableFrom<IEnumerable<User>>(result);
            model.Count().Should().Be(3);
            Assert.Throws<NullReferenceException>(() => 
            _controller.GetUsers().Exception);
        }

When I run tests, everything gets green status, however inside the controller class I cannot see a 'green tick' next to the lines with catch block scope. I'd really like to know how to write proper code for testing an exceptions inside catch blocks!

1 Answer 1

3

Another test is needed that will cause the exception to be thrown when being exercised.

For example

[Fact]
public async Task GetUsers_WhenCalled_HandlesException() {
    //Arrange
    var mockRepo = new Mock<IRepositoryWrapper>();
    mockRepo
        .Setup(repo => repo.User.GetAllUsersAsync())
        .ThrowsAsync(new InvalidOperationException());

    var controller = new UsersController(mockRepo.Object, _logger, _service);

    //Act
    var result = await controller.GetUsers();

    //Assert
    Assert.IsNull(result);
    //Can also assert what logger records
}

In the above example, when GetAllUsersAsync is invoked, it will throw an exception that will be caught in the try-catch and allow the code to flow as intended for the test.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! That's actually works. All I had to do, was to add one more Mock for ILogger<UsersController> fake and pass it to UsersController initialization.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.