简体   繁体   中英

Should I force exceptions to test them?

i have this method in my data access class and i have a unit test to make sure it does work properly, but my test doesn't test the exception so my question is should i create a new test to force the exception to be raised or should i just trust that the catch block will work just fine in case of an exception ? is it worth the effort ?

here is an example :

public void UpdateProject(Project project)
    {
        using (var transaction = _session.BeginTransaction())
        {
            try
            {
                _session.Update(project);
                _session.Flush();
                transaction.Commit();
            }
            catch (HibernateException)
            {
                transaction.Rollback();
                throw;
            }
        }
    }

Ideally, you should try to test every line of code that you can... this would mean forcing an exception to occur to test the exception handler, and make sure this works properly.

In practice, there will always be some lines of code not covered - however, I would force exceptions via mocking in order to test any exception handler that you feel is critical, especially, or that will possibly happen in production.

In Linux kernel, 80% of bugs in drivers are in error-handling code.

Exceptional handling is the source of many errors and you surely should test all the exception paths.

Of course you can't test every line of code. But the statistic says that programmers pay less attention to exception handling, so you must test them thoroughly.

Here are my rules for ideal testing of failure behavior:

  • If you are using dependencies that might throw exceptions, then you should include unit tests that make your mocks of them throw exceptions.
  • If under certain conditions your code should throw exception, then you should include unit tests that sets up such conditions.

The first lets you know what your code behaves like under external failure, and often leads to reconsiderations of what to do. In all situations it is good to see what actually happens. The second just makes sure that you hold what you promise, as far as the errors your code should detect and consider exceptional. It is no different than testing other features in your code.

Before considering the unit-test suite complete, one should have a peek at code-coverage of the code under test. For non-trivial code, there is almost always one way my code branch that my unit tests do not cover, or worse, has behaviour I did not intend. Surprisingly often, the solution is to remove that code rather than adding more tests. Just cruft left behind when winging it earlier.

I'm not necessarily saying that one should reach 100% coverage, but one should do code coverage driven unit testing because it is a more visual way to understand and expose the code behaviours that exists. Just looking at it can give you new ideas for how to refactor code to achieve Single Responsibility Principle and Separation of Concerns .

You could get your session to mock throwing an exception but there is little need to test that a catch works.

It's not wrong to write a test to check a transaction is rolled back if an update throws an exception but at a gut level i think this is taking it too far.

Maybe a more elaborate case would warrant it.

On an extra note, would you not rollback upon any type of exception?

I hope the transaction will be Rollback if Displose() is called before Commit() therefore do you need the catch at all?

As to other cases, if your catch does more then just log the problem, I think it should be unit tested. However don't let the fact you can not do profit unit testing stop you from doing some unit testing.

From the exception name (HibernateException) I would think it's not an exceptional case. So it can happen during normal operation. If that's the case I would make a test that causes the exception to make sure it gets handled properly.

I would certainly test each specific exception that is caught and handled. At least you have some execution path through your handling code which should give you some comfort that nothing else weird will happen when/if you ever encounter such an exception during runtime.

Remember, you only need to test the code you want to work.

I sure hope you would separately test transaction.Rollback() with the tests that exhaust all possible situations you can think of. However, provided that testing was exhaustive, I would probably not bother raising an exception since there's nothing else in the handler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM