Re: assertThrows(myObject).methodCall()

Thomas Mueller <[email protected]> Fri, 8 Jul 2011 11:25:56 +0200
Newsgroups gmane.comp.java.junit.devel
Message-ID <CAKpgiBaqS6174jthbdMTOR6N5kLdNe=RKqeSs5n2ZUszNrB-PA@mail.gmail.com>
Hi,

> No, we're unlikely to include it in base JUnit, because the reflection
> magic is likely to not work on all platforms that JUnit currently
> works on, and, as you point out, it won't work on final classes, or
> any classes without CGLIB, etc.

I understand. Well, java.lang.reflect.Proxy is supposed to run
everywhere, but it does make sense to try it out in an experimental
project.

> However, it's an absolutely perfect idea for junit.contrib, the
> companion project for experimental code, which I'm trying to get off
> the ground. =A0The submission process to junit.contrib is still
> relatively undefined (which is why there's no code there yet). =A0Would
> you be interested in being a charter contributor?

Sure. You need to tell me what the directory structure and so on is
supposed to look like.

I can write a patch for assertThrows as it is now (to support
interfaces only; without any bytecode manipulation), together with
some documentation. That alone solves 90% of the problem.
Non-interface methods will require more work. I'm not sure if it makes
sense to "role your own" bytecode generation, or depend one of the
existing libraries (bcel, asm, cglib). It sounds like what
assertThrows needs is a small subset of what those tool can do. I do
have a little bit of experience with bytecode (re-construct the source
code from the bytecode for my JaQu tool -
http://www.h2database.com/html/jaqu.html) and will try, but I can't
promise much. With this, you are at 98%. Still remaining are static
methods and final classes. This is even more complicated, but maybe
there is a way - see http://code.google.com/p/powermock/ and
http://projectlombok.org/

To make the method sound less weird, I would document it as follows:

Object assertThrows(Object o)
Creates a verifying proxy for an object, which checks each method call
throws an exception. Example:

// Wrap the object into a proxy
List proxyList =3D assertThrows(myList);

// This will internally call myList.get(0) and verify it throws an exceptio=
n.
// If it doesn't throw an exception, then the proxy calls Assert.fail().
proxyList.get(0);

// Simplified usage
assertThrows(myList).get(0);

--------------------

Then, what about:

// check the method call is relatively fast / slow
assertFast([maxMillis,] myObject).myMethod()
assertSlow([maxMillis,] myObject).myMethod()

I don't have a use case for those, but probably others.

// call the method in a loop (with a 10 ms delay) until it returns the
expected result
assertEventuallyTrue([maxMillis,] myObject).myMethod()
assertEventuallyFalse([maxMillis,] myObject).myMethod()

I do have an actual use case for assertEventuallyTrue/False: my
program is supposed to delete files in a background thread within some
non-deterministic time. And I don't want to use Thread.sleep(..)
because it slows down testing unnecessarily (usually, the thread is
quick).

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