views:

110

answers:

3

Hi,

Looking at our code coverage of our unit tests we're quite high. But the last few % is tricky because a lot of them are catching things like database exceptions - which in normal circumstances just dont happen. For example the code prevents fields being too long etc, so the only possible database exceptions are if the DB is broken/down, or if the schema is changed under our feet.

So is the only way to Mock the objects such that the exception can be thrown? That seems a little bit pointless. Perhaps it's better to just accept not getting 100% code coverage?

Thanks, Dan

+1  A: 

A common practice when a 100% coverage goal is specified is to cover as much code as possible by test and cover the remaining few percents by code review.

mouviciel
Shouldn't you be covering the rest of code by code review as well?
Mark
Of course yes. But this specific review aims at justifying why that code part was not tested and why it should not harm not to test it.
mouviciel
Ok fine. However is it possible to mark code as "not to be covered"? At the moment we have no clear way of identifying from the coverage report which code has been "code reviewed" and deemed ok and which hasnt? So i'd like to get to a kind of pseudo 100% coverage where all code has been tested, or reviewed. (The tool we use is EclEmma)
Codek
Usually you just put a comment on the line indicating that the line has been reviewed. Good code coverage tools should provide a way to filter out lines with appropriately formatted comments indicating the line is not expected to be covered. I have no idea whether EclEmma provides this ability.
Christopher Barber
A: 

Usually when running into low-level exceptions, like IOException or SQLException in Java, I wrap them into a exception extending RuntimeException. I feel testing this behavior is quite important because otherwise there is the very nasty possibility of accidentally swallowing the exception.

So I do recommend testing them, if you actually do something when a low-level exception is thrown.

Edit: Added example.

public void store(User user) {
    try {
        userDao.store(user);
    } catch (IOException e) {
        // Logging, perhaps some logic.
        throw new ServiceException(e);
    }
}

@Test(expected = ServiceException.class)
public void Store_Fail() {
    UserDao userDaoMock = createMock(UserDao.class);
    User user = // Create test user.
    userDaoMock.store(user);
    replay(userDaoMock);
    userService.store(user);
    verify(userDaoMock);
}

There isn't much to test here, but if the logic requires for a ServiceException to be thrown why not test it?

ponzao
Ok. So how do you test yours? Do you mock the error, or do you find a way to genuinely trigger it somehow?
Codek
@Codek I go with mocking. In that specific test case I inject a mock object into the tested class and force it to throw an exception in the tested call. I don't attempt to cause any sort of file or database errors because it is very time consuming and sometimes it isn't even clear why the method would throw the checked exception.
ponzao
A: 
So is the only way to Mock the objects such that the exception can be thrown?

I believe that will be the easiest way, but you could also do a stub (aka a object that extends the real object, and forces behvior like throwing an exception everytime). Or you could use AOP, but I think using a library like easymock or jmock is going to be the easiest way to go.

That seems a little bit pointless. Perhaps it's better to just accept not getting 100% code coverage?

Whenever I speak on this topic I like to shift people's mindset from worrying about a certain percentage of coverage, and instead to use the percentage as a tool to make you a better developer. Put another way having 100% coverage or 50% coverage does not necessarily mean your code is well written or even working but using Code Coverage as key indicator when you are developing code as to if you have been slacking on writing tests etc... is a good idea.

My personal opinion about your question is that if it is logic your application is doing, then it is worth testing. So if you are catching and exception and retuning false from the method, you should have a test for that. If you are catching the exception and wrapping it in another exception you should test that. If you are catching the exception and doing nothing, then that should be a code smell that needs to be fixed because that can lead to all kinds of unmanageable side effects.

As to whether 100% is not wroth it, I would say yes it is not worth it. You should find a good comfort level for yourself (maybe 80%, maybe 90%) and stick with it. But I would not base it on the types of tests (like testing exception logic) it should just be based on total coverage and seen as an indicator that you are not writing your tests when you commit code.

Daniel Roop