-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Method Proposal: ExpectedException#expect(Throwable, Callable) #706
Comments
Although I contributed to ExpectedException, I have to admit that I personally just use try/catch in most of my tests that involve exceptions. Agreed that once Java 8 is widely usable, the syntax becomes much more appealing. |
I've done something similar for stefanbirkner/system-rules#5. Just one difference: I created a new interface Assertion with a no-args void method checkAssertion(): http://www.stefan-birkner.de/system-rules/#ExpectedSystemExit |
@stefanbirkner the rule is different. If you or somebody else already implemented my Rule, then the things would be more simple to commit to JUnit. |
@Tibor17, to be precise, we've tried, twice (with @test(expected=Foo.class) and ExpectedException) to duplicate functionality that Java's already had since its birth. In both cases, I've found eventually that the framework solutions are harder to read and reason about for large teams, and are just as easy to use mistakenly, as vanilla try/catch. If there's a best-practices document that says differently, it would be interesting to talk to the author and understand how their experience differs. In this case, the method you suggest is easily implemented as a static method in a team's code repository without any changes to JUnit. Again, when Java 8 is widely used, I can then see that the savings in typing would merit considering something like this as something to bless as an "official" JUnit extension. Although in my Java 8 meanderings, I tend to use a thrown() method that takes a block and returns any exceptions thrown, so that you can assert anything you want about the exception: assertEquals(Exception.class, thrown(() -> foo()).getClass()); or: assertEquals("yikes!", thrown(() -> foo()).getMessage()); |
@dsaff It is easy to say how the assert would look like now, but we have to talk about real calls next year when the Java 8 will be out. There is #722 with some examples. As you can see I am not the only who requested. Most probably there will be discussions about returned values out of the block, assert signatures, Matchers for classes, Matchers for exception messages, etc. Perhaps Hamcrest will take care of new assertions next year, who knows. With the current status of Java 8 Lamba expressions you can already design pure Java signatures for assertThat: |
I was just wishing for the same! How about: assertThrows(Exception.class, () -> foo());
assertThrows(Exception.class, () -> foo(), e -> assertEquals("yikes!", e.getMessage())); Note that unlike @Tibor17, I'm suggesting a third argument that allows for adding additional checks on the @FunctionalInteface
interface ThrowableRunnable {
void run() throws Throwable;
}
static void assertThrows(
Class<? extends Throwable> throwable,
ThrowableRunnable runnable
) {}
static <T extends Throwable> void assertThrows(
Class<Throwable> throwable,
ThrowableRunnable runnable,
Consumer<T> exceptionConsumer
) {} Note also that neither |
@lukaseder Callable#call() throws Exception. That's fine Java API design because if you suppose an expected exception like RuntimeException or an Error, then these two subtypes are unchecked and therefore they are not mentioned in the signature of |
http://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
I agree with the part about Note, I haven't given all of this too much thought, and I'm not well acquainted with Hamcrest, so your assessment may well be more reasonable in a broader context. |
I agree with using Throwable. |
I like the general idea! We just need to get the details right... ;-) For instance, I'm not very fond of the name @Tibor17 How would you use |
I forgot to mention assertNotThrows(). |
@Tibor17 I am well aware of the benefits of using the rule |
@marcphilipp |
@marcphilipp |
No, I don't think so. Feel free to go ahead and submit a pull request. |
@Tibor17 Sorry, that I'm entering the discussion only now. A few weeks ago I created a library named Vallado. If I understand your concern right, then this library solves it. assertEquals(1, objectUnderTest.property);
when(() -> objectUnderTest.doSomething()).thenA(RuntimeException.class).isThrown();
assertEquals(2, objectUnderTest.property); With Java 8 (or with an anonymous class) statements could be executed directly within the test method. You don't need to implement a rule interface. Hence you can create an own microlibrary for your concern that is independent from the JUnit framework and therefore usable by other test frameworks like TestNG, too. |
@Tibor17 Does Vallado solve your problem? |
@stefanbirkner |
Not quite sure why a fluent interface would only be useful in BDD. Guice, Truth and Guava all have classes with fluent interfaces. I think the syntax that @stefanbirkner solves a few of the more annoying problems of the other solutions. With I personally would rather see what other frameworks end up using for specifying that an assertion is thrown and making assertions on the properties of the exception, and then if there's an obvious winner, either endorse it or integrate a similar API in JUnit. JUnit doesn't need to solve everyone's assertion problems. |
Fixed in #1154 |
Many times I needed to assert a block of code in test-method to throw an exception, and check how the throwing block has changed values.
I had to use try-catch.
So I would like to implement new method with such of signature
ExpectedException#expect(Throwable, Callable)
.Usage:
Object obj = expect( Exception.class , new Callable() { ..do and return something.. });
Usage of Lambda in Java 8:
expect( Exception.class , () -> { ..do and return something.. } )
The text was updated successfully, but these errors were encountered: