最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why is my global error handling not triggered when I throw a mock exception in my c# unit test? - Stack Overflow

programmeradmin1浏览0评论

I'm learning on how to write unit tests. From what I gathered, if I want to unit test a controller in a C# API, I need to mock/fake the inputs, the outputs and all dependencies of it. Next, I want to see what happens when my controller encounters an exception in its logic, so I fake an exception like below code

The unit test

        [Fact]
        public async Task GetCustomerById_FailedByDbOps()
        {
            // Arrange
            var customerId = 1;
            _customerRepoMock
                .Setup(repo => repo.GetOne(customerId))
                .ThrowsAsync(new Exception("Wrong or missing DB conn string"));

            // Act
            var result = await _controller.RetrieveCustomerById(customerId);

            // Assert
            var objResult = Assert.IsType<ObjectResult>(result);
            Assert.Equal(500, objResult.StatusCode);
        }

And I've already registered a global exception handler for my app

builder.Services.AddExceptionHandler<MyGlobalExceptionHandler>();

I expect the test to pass, as the global exception handler should be triggered, and return a custom error object based on the logic in MyGlobalExceptionHandler. But instead, the test failed with the mock exception itself.

Why is that? Did I do something wrong here? Or is it that a global exception handler can’t be triggered in unit tests? It works fine when I run the application locally.

I'm learning on how to write unit tests. From what I gathered, if I want to unit test a controller in a C# API, I need to mock/fake the inputs, the outputs and all dependencies of it. Next, I want to see what happens when my controller encounters an exception in its logic, so I fake an exception like below code

The unit test

        [Fact]
        public async Task GetCustomerById_FailedByDbOps()
        {
            // Arrange
            var customerId = 1;
            _customerRepoMock
                .Setup(repo => repo.GetOne(customerId))
                .ThrowsAsync(new Exception("Wrong or missing DB conn string"));

            // Act
            var result = await _controller.RetrieveCustomerById(customerId);

            // Assert
            var objResult = Assert.IsType<ObjectResult>(result);
            Assert.Equal(500, objResult.StatusCode);
        }

And I've already registered a global exception handler for my app

builder.Services.AddExceptionHandler<MyGlobalExceptionHandler>();

I expect the test to pass, as the global exception handler should be triggered, and return a custom error object based on the logic in MyGlobalExceptionHandler. But instead, the test failed with the mock exception itself.

Why is that? Did I do something wrong here? Or is it that a global exception handler can’t be triggered in unit tests? It works fine when I run the application locally.

Share Improve this question asked Feb 6 at 10:06 SonnySonny 3262 gold badges6 silver badges16 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

Exception handling middleware will handle exceptions only after the controller will throw it (note that not only builder.Services.AddExceptionHandler... should be called but as far as I can see - app.UseExceptionHandler... too). So your controller still throws the exception in RetrieveCustomerById which will be handled later.

There are two ways to go from here - either verify the exception with Assert.Throws(Async) instead of expecting the status code or go with the integration testing ASP.NET Core approach where you will start up the whole application and test the whole pipeline (you still can mock the dependencies here).

See also:

  • ASP.NET Core Middleware - details on how middlewares work and their order
  • Integration tests in ASP.NET Core
  • Integration test and hosting ASP.NET Core 6.0 without Startup class
发布评论

评论列表(0)

  1. 暂无评论