assertThrows(myObject).methodCall()
Thomas Mueller <[email protected]> Thu, 7 Jul 2011 22:10:25 +0200
| Newsgroups | gmane.comp.java.junit.devel |
|---|---|
| Message-ID | <CAKpgiBa4umXFQJH18K4WTt1YCSGSkOu_fde0ra8ARxB7HppSpg@mail.gmail.com> |
Hi,
I have many test cases that expect an exception to be thrown. I want
to verify that a given method of my code will actually throw an
exception in a given test case. What I want is described here:
http://stackoverflow.com/questions/156503/how-to-assert-that-a-certain-exception-is-thrown-in-junit4-5-tests
- Example (please not my actual use case isn't ArrayList - this is
just an example):
List<String> myObject = new ArrayList<String>();
// current pattern - 6 lines of code
try {
myObject.get(0);
fail();
} catch (IndexOutOfBoundsException e) {
// expected
}
Now, I have a few problems with this. First, it's 6 lines of code,
which is a lot. Then, it's too easy to forget 'fail()' (I forgot it in
many cases). I know I could refactor the test to move it to a separate
method, and add @Test(expected=IndexOutOfBoundsException.class) (the
top answer on StackOverflow) - but that's ugly as well. I don't _want_
a separate test method.
I found a solution to simplify the test, by creating a new helper
method 'assertThrows' (implementation below), so that my test case is
now:
// shorter, 1 line
assertThrows(IndexOutOfBoundsException.class, myObject).get(0);
// even shorter (if I don't care what kind of exception)
assertThrows(myObject).get(0);
My solution currently uses a Java proxy (which obviously only works
for interfaces), but using CGLIB it would be possible to support
(non-final) regular classes as well. Anyway, for reference, my
solution is here:
http://h2database.com/p.html#554bf1f041969cba0f6fa1a6e8e20cba - my
solution checks that a method was called by miss-using finalize, which
is OK for my use case (there are probably better solutions for this).
I know there are other solutions. I do know this has been discussed
before on the JUnit list:
http://old.nabble.com/assertNotEquals-and-assertThrows-td3423551.html
I also know that JUnit 4.7+ has "Rules" but I really don't want to
write one method for each test. It's ugly because it forces me to
split a test into many tiny methods. I don't like this. For example, I
have test code like this:
assertThrows(stat).execute("select sum(id) from test for update");
assertThrows(stat).execute("select distinct id from test for update");
assertThrows(stat).execute("select id from test group by id for update");
assertThrows(stat).execute("select t1.id from test t1, test t2 for update");
Every *line* would have to be in it's own method.
I have the feeling my feature request will reject it because it would
force JUnit to include a proxy mechanism like CGLIB (which I guess
isn't included now; maybe I'm wrong). And you will probably it's a bit
hacky (well, it is). But it *is* very useful (at least in my view).
I have already submitted this request to Mockito, but they are not
interested that much - they wrote this feature is something that JUnit
is supposed support, as it's not that much related to what Mockito
does.
So, what do you think?
Regards,
Thomas
------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2d-c2