ArchUnit: How to check if method throwing an exception also declares it - java

I'm trying to write an ArchUnit test which tests if a certain unchecked exception when thrown is also declared by that method, and recursively, if any method calling that method also declares it.
The intention is to ensure these exceptions are documented everywhere, and, since I can enforce anything that is declared to be thrown has to be documented (other tools can enforce this), this seemed a good way to go about it.
The scope of these checks can be limited to a certain package; ie. treat runtime exception X when used within package Y as a "checked" exception, and enforce it with a rule.
Passing code:
void someMethod() throws MyRunTimeException {
throws new MyRunTimeException();
}
void anotherMethod() throws MyRunTimeException {
someMethod();
}
Failing code:
void someMethod() { // doesn't declare exception
throws new MyRunTimeException();
}
void anotherMethod() { // should declare exception when someMethod declares it
someMethod();
}
Now I think I can detect methods that do not declare the exception as follows:
noMethods().should().declareThrowableOfType(MyRunTimeException.class)
And I think I can detect calls to create this exception (even better would be when it is actually thrown, but I couldn't find that):
noClasses().should().callConstructorWhere(
target(is(declaredIn(MyRunTimeException.class)))
.and(not(originOwner(is(assignableTo(MyRunTimeException.class)))))
);
... but I see no way how I could combine these two rules.
For some reason however ArchUnit only allows checking calls from classes, but not from methods (which seems to make more sense). In other words, I couldn't find a way to check calls given a method:
noMethods().should().callConstructorWhere( ... )
Or:
noMethods().should().throw(MyRuntimeException.class)
.and(not(declareThrowableOfType(MyRunTimeException.class)))
Any idea how I could go about enforcing such a rule?

You're right that the fluent MethodsShould API (as of ArchUnit 0.23.1) does not seem to support method calls, but as the information is present in the domain objects (see JavaCodeUnit, e.g. getMethodCallsFromSelf, getConstructorCallsFromSelf, or more generally getAccessesFromSelf), you can always implement a custom ArchCondition.
With
import static com.tngtech.archunit.base.DescribedPredicate.doNot;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.have;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.codeUnits;
import static java.util.stream.Collectors.toSet;
I'd use the following tests:
#ArchTest
ArchRule codeUnits_should_declare_all_RuntimeExceptions_they_throw = codeUnits()
.that(doNot(have(owner(assignableTo(RuntimeException.class)))))
.should(new ArchCondition<JavaCodeUnit>("declare all RuntimeExceptions they throw") {
#Override
public void check(JavaCodeUnit codeUnit, ConditionEvents events) {
// TODO: ArchUnit 0.23.1 might not have an API to get exceptions actually thrown.
// As a first approximation, the following code collects all RuntimeExceptions that are instantiated
// – which has false positives (exceptions that are instantiated, but not thrown),
// as well as false negatives (exceptions that are created via factory methods and thrown).
// Accounting for the false negatives in the same way as here is left as an exercise for the interested reader.
Set<JavaClass> instantiatedRuntimeExceptions = codeUnit.getConstructorCallsFromSelf().stream()
.map(JavaAccess::getTargetOwner)
.filter(targetClass -> targetClass.isAssignableTo(RuntimeException.class))
.collect(toSet());
boolean satisfied = codeUnit.getExceptionTypes().containsAll(instantiatedRuntimeExceptions);
String message = String.format("%s does%s declare all RuntimeExceptions it instantiates in %s",
codeUnit.getDescription(), satisfied ? "" : " not", codeUnit.getSourceCodeLocation());
events.add(new SimpleConditionEvent(codeUnit, satisfied, message));
}
});
#ArchTest
ArchRule codeUnits_should_declare_all_RuntimeExceptions_of_methods_they_call = codeUnits()
.should(new ArchCondition<JavaCodeUnit>("declare all RuntimeExceptions of methods they call") {
#Override
public void check(JavaCodeUnit codeUnit, ConditionEvents events) {
Set<JavaClass> runtimeExceptionsDeclaredByCalledMethods = codeUnit.getMethodCallsFromSelf().stream()
.map(JavaAccess::getTarget)
.map(MethodCallTarget::resolveMember)
.filter(Optional::isPresent)
.map(Optional::get)
.flatMap(method -> method.getExceptionTypes().stream())
.filter(exceptionType -> exceptionType.isAssignableTo(RuntimeException.class))
.collect(toSet());
boolean satisfied = codeUnit.getExceptionTypes().containsAll(runtimeExceptionsDeclaredByCalledMethods);
String message = String.format("%s does%s declare all RuntimeExceptions of methods they call declare in %s",
codeUnit.getDescription(), satisfied ? "" : " not", codeUnit.getSourceCodeLocation());
events.add(new SimpleConditionEvent(codeUnit, satisfied, message));
}
});

Related

Can I ignore aspect of a method while mocking it using Mockito?

I have a class with a few methods advised through an input validation aspect (validates whether all input parameters are not-null/non-empty strings).
I am facing an issue while writing test case for them and want to verify if this is indeed a bad design issue.
Here's a very simplified version of my class:
public class A {
public String one(String word) {
// Some actions
String val = two(word2);
// Some more actions
}
protected String two(String word) {
// Some actions
}
}
Now while writing test cases for one() I use Mockito and want to mock calls to two(). So I use:
#Spy
A a;
#Test
void test() {
doReturn("Bye").when(A).two(Mockito.anyString());
a.one("hello");
// Some validations
}
This test fails as the: doReturn() line fails with input being empty for two().
Should I not mock two() or can I make this work somehow?
Edit:
Adding a more specific example related to the two methods being present in two different classes as requested:
Create a page through a WebService. This builds a putRequest, executes it and returns a response.
public class AUtility implements BaseUtility {
public Response create(Params params) {
try {
PutMethod putRequest = buildPUTRequest(params.getAttr1(), params.getAttr2());
return Utils.buildResponse(client.executeMethod(putRequest),
params.getAttr3(),
params.getAttr4());
} catch (Exception e) {
throw new AppException(e);
}
}
}
The put request marshals the data into a file to write it through the HttpClient
private PutMethod buildPUTRequest(final String url, final Object obj) throws IOException, JAXBException {
// Create a temp file to store the stream
File tempFile = File.createTempFile(APPLICATION_LABEL, XML_LABEL);
decoder.marshal(obj, tempFile);
// Build the put method
return putMethod;
}
XMLMarshaller
public interface XMLDecoder implement Decoder {
public void marshal(Object obj, File tempFile) throws IOException, JAXBException {
// Perform marshalling operations
}
}
The test fails on line2 with the inputs being null.
#Test
public void createPageParamsHttpException() throws HttpException, IOException, JAXBException {
expectedException.expect(AppException.class);
doNothing().when(decoder).marshal(Mockito.anyString(), Mockito.any(File.class));
doThrow(HttpException.class).when(client).executeMethod(Mockito.any(HttpMethod.class));
Params params = new Params(new Application(),
APPLICATION_URL_LABEL,
SITE_NAME_LABEL,
URL_WITHOUT_HTTP_N_HTML);
utility.createPage(params);
}
Any idea how should I proceed for the same?
You don't want to do this.
You are inherently changing the behavior of the class. If you change what two() does, how do you know that one() will do what it's supposed to do in production?
If you truly want to do this, you should extract the behavior of two() into another top level class, and then inject the dependency into A. Then you can mock this dependency and you don't have to worry about going to the trouble of creating a partial mock for A.
In a similar vein, if you must keep two in the same class (because it's behavior is part of the same responsibility that is assigned to A - see the Single Responsibility Principle - why is it public?
The reason you are having trouble is because you are violating the SRP, see my note above. You said this:
This builds a putRequest, executes it and returns a response.
You should not be trying to test the behavior of all three of those things at the same time. Ultimately, this method does not really do anything. The buildPUTRequest method does, and shouldn't be in a class called AUtility, it should be in a class RequestFactory. Then, you would want to test the Utils.buildResponse method, except that shouldn't be in a class called Utils, it should be in a class called Responder or something... and this method ABSOLUTELY should not be static.
Work on naming your classes better things, and if you can't come up with a good name, that means the class probably does too much and should be refactored. And a method that wraps the work in two other methods doesn't need to be unit tested. Integration tested, perhaps, but that's another story.

Groovy casting collection unasked for it

I have some code written in Java that uses Generics. This is a simple version:
// In Java
public interface Testable {
void test();
}
public class TestableImpl implements Testable {
#Override
public void test(){
System.out.println("hello");
}
}
public class Test {
public <T extends Testable> void runTest(Collection<T> ts){
System.out.println("Collection<T>");
for(T t: ts)
t.test();
}
public void runTest(Object o){
System.out.println("Object");
System.out.println(o);
}
}
// in Groovy - this is how I have to use the code
Test test = new Test()
test.runTest([new TestableImpl(), new TestableImpl()])
test.runTest([1,2,3]) //exception here
I am suprised that the second method call is dispatched to the wrong method (wrong in my Javish understanding). Instead calling the Object overload, the Collection gets called.
I am using Groovy 2.1.9, Windows 7.
And the exception is:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException:
Cannot cast object '1' with class 'java.lang.Integer' to class 'Testable'
org.codehaus.groovy.runtime.typehandling.GroovyCastException:
Cannot cast object '1' with class 'java.lang.Integer' to class 'Testable'
Why? How to solve this?
How to make Groovy call the same method as Java would?
edit: to further explain the case, I'd like to write a Spock test for it (just imagine the method returns something, say a String..):
def "good dispatch"(in,out) {
expect:
test.runTest(in) == out
where:
in | out
new Object() | "a value for Object"
new Integer(123) | "a value for Object"
[1,2,3] | "a value for Object"
[new TestableImpl()] | "a value for Testable Collection"
}
Others have suggested possible ways to solve your problem but here is WHY it happens.
Groovy - being a dynamic language - uses the runtime type information to invoke the correct method. Java, on the other hand, determines which method will be used based on the static type.
A simple example that demonstrates the differences between JAVA and GROOVY:
void foo(Collection coll) {
System.out.println("coll")
}
void foo(Object obj) {
System.out.println("obj")
}
In GROOVY:
Object x = [1,2,3] //dynamic type at invocation time will be ArrayList
foo(x)
//OUT: coll
In JAVA:
Object x = Arrays.asList(1,2,3);
foo(x);
//OUT: obj
Collection x = Arrays.asList(1,2,3);
foo(x);
//OUT: coll
Now in your example (it does not really have anything to do with the use of generics):
test.runTest([new TestableImpl(), ...]) //ArrayList --> collection method will be used
test.runTest([1,2,3]) //also ArrayList --> best match is the collection variant
If multiple dispatch is not what you want, can you cast the argument in the test script?
test.runTest( (Object) [1,2,3] )
This happens because Java strips the generic information from the code at compile time.
When Groovy tried to select the correct method at runtime, it gets an ArrayList as parameter for the second call (note: No generic information anymore) which matches runTest(Collection tx) better than runTest(Object o).
There are two ways to solve this:
Create two methods with different names
Delete runTest(Collection). Instead use instanceof in runTest(Object) to determine whether the argument is a collection of the correct type and delegate to a new internal method runTestsInCollection().
Lets start from the solution:
import groovy.transform.CompileStatic
import spock.lang.Specification
import spock.lang.Subject
class TestSpec extends Specification {
#Subject
Test test = new Test()
def 'Invokes proper method from JAVA class'() {
given:
List input = [1,2,3]
when:
invokeTestedMethodJavaWay(test, input)
then:
noExceptionThrown()
}
#CompileStatic
void invokeTestedMethodJavaWay(Test test, Object input) {
test.runTest(input)
}
}
First of all, you cannot override methods by generic type even in JAVA. For example if you try adding another method with same contract but overloaded with different generic type, let say public <P extends Printable> void runTest(Collection<P> ps) you will run into disambiguation problem as both methods will have same erasure.
What's more important in your question, has been already stated in other answers here. Your expectations didn't meet the behaviour as we are getting into compile vs runtime types evaluation between respectively JAVA and Groovy. This can be very useful if one is aware of this. For example when handling exceptions. Consider following example.
JAVA:
public void someMethod() {
try {
// some code possibly throwing different exceptions
} catch (SQLException e) {
// SQL handle
} catch (IllegalStateException e) {
// illegal state handle
} catch (RuntimeException e) {
// runtime handle
} catch (Exception e) {
// common handle
}
}
Groovy:
void someMethod() {
try {
// some code possibly throwing different exceptions
} catch (Exception e) {
handle(e)
}
}
void handle(Exception e) { /* common handle */ }
void handle(IllegalStateException e) { /* illegal state handle */ }
void handle(RuntimeException e) { /* runtime handle */ }
void handle(SQLException e) { /* SQL handle */ }
I find Groovy way much cleaner than nasty try-catch multi block, especially that you can implement all handle methods in separate object and delegate handling. So it's not a bug, it's a feature :)
Getting back to the solution. You cannot annotate whole Spock's test class with #CompileStatic as you already know. However you can do this with a single method (or separate helper class). This will bring back expected java-like behaviour (compile time type evaluation) for any call from within annotated method.
Hope this helped, cheers!
PS. #Subject annotation is only used for the sake of readability. It points which object is under test (is subject of the specification).
EDIT:
After some discussion with the author of the question, not so clean but working solution:
import groovy.transform.CompileStatic
import spock.lang.Specification
import spock.lang.Subject
class TestSpec extends Specification {
#Subject Test test = new Test()
TestInvoker invoker = new TestInvoker(test)
def 'Invokes proper method from JAVA class'() {
when:
invoker.invokeTestedMethod(input)
then:
noExceptionThrown()
where:
input << [
[1, 2, 3, 4, 5],
[new TestableImpl(), new TestableImpl()]
]
}
}
#CompileStatic
class TestInvoker {
Test target
TestInvoker(Test target) {
this.target = target
}
void invokeTestedMethod(Object input) {
target.runTest(input)
}
void invokeTestedMethod(Collection input) {
if (input.first() instanceof Testable) {
target.runTest(input)
} else {
this.invokeTestedMethod((Object) input)
}
}
}
If you would need to check by more than one generic type of collection, please notice that instanceof can be used in switch case statements in Groovy.

Java Refactoring of Exception Handling Best Practice

Description:
I am always told by people check all your parameters all the time which results in a lot of if checks and try catches.
Question:
In the code below I cleaned the code such that only method that handles the exception handling is at the root method that is exposed publicly and not in the refactored private helper methods. Is this practice ok?
I'm not handling exceptions closer to the methods they could occur in but the code is much cleaner.
Code Notes:
Method validateInputs() not included.
ParameterObject a is derived let say from parameters created through "someCode", it represents parameters I want to pass around. Anytime I have a need for more than 2 parameters i refactor those parameters to a parameter object.
Code:
public class UnderTest {
public UnderTest() {}
public boolean runWork( String someValue ) throws CustomException
{
try
{
validateInputs();
// someCode
.
.
processWork( ParameterObject a );
}
catch( Exception e )
{
logError(e);
}
}
private void processWork( ParameterObject a )
{
Operation1( ParameterObject a );
Operation2( ParameterObject a );
}
private void Operation1( ParameterObject a )
{
// someCode
}
private void Operation2( ParameterObject a )
{
// someCode
}
private void logError(Exception e)
{
throw new CustomException(e,"Message");
}
}
I tend to check arguments when they enter the class by some public API. In private methods I check only by assertions or not at all. This implies that I trust my own class a bit more.
I would opt for a bit of both. Validating inputs is always a good idea and libraries such as the Apache commons-lang Validate class can make this easier. Generally speaking, an incorrect argument should cause a runtime exception (usually IllegalArgumentException or NullPointerException). How deeply you go into your private methods to do input validation is a matter of taste. Remember that the sooner you spot an invalid argument, the more helpful the error message is going to be.
Of course, this assumes you document your public facing APIs well (and ideally your internal methods too). Make it clear what is valid for your inputs.

How can I make IntelliJ IDEA understand my null-checking method?

I have a method where a parameter is marked with the #Nonnull annotation. The code which calls the method has to check whether the value is null. Rather than just a straight x != null check, it is calling a utility method on another class. (In the real code, the utility method also checks whether it is a blank String).
My problem is that Intellij Idea is showing an inspection warning on the Nonnull method call, saying that my variable "might be null". I know it cannot be null because of the utility method check - how can I tell the inspector that?
Since that is a bit abstract, here's a minimal example of what I mean:
package org.ethelred.ideatest;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
* tests annotations
*/
public class AnnotationChecker
{
public static void main(String[] args)
{
String x = null;
if(args.length > 0)
{
x = args[0];
}
if(!isNull(x))
{
useObject(x);
}
if(x != null)
{
useObject(x);
}
}
public static boolean isNull(#CheckForNull Object o)
{
return o == null;
}
public static void useObject(#Nonnull Object o)
{
System.out.println(o);
}
}
This uses the JSR 305 annotations.
In this example, in the first call to useObject Intellij puts a warning on the x parameter saying "Argument 'x' might be null". In the second call, there is no warning.
In IDEA 13 very fancy feature was added, called Method Contracts. For example, you could have a method, that throws validation exception if it encounters null:
#Contract("null -> fail")
public static void validateNull(#Nullable final Object object) {
if (object == null) {
throw new ValidationException();
}
}
IDEA will analyze the annotation and won't show up warnings, if you call it before possible NPE:
validateNull(user);
user.setSomething("something"); // no warning
You have full documentation in IDEA's settings (just search for Method Contract). For this to work you need additional dependency on jetbrain's annotations jar:
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>13.0</version>
</dependency>
With IDEA 12 you can configure the NotNull-check methods:
http://youtrack.jetbrains.com/issue/IDEA-35808#tab=Comments
I don't believe there's any way to resolve the warning with the code written as it is. I was hoping to find that IntelliJ supports a value for #SuppressWarnings that you could use on the useObject(x) statement, but according to this source it does not. You may just have to bite the bullet and change your code to something like the following:
if (x != null && !isBlank(x)) {
useObject(x);
}
Notice that I renamed the method isNull to isBlank since it is my understanding that the actual method you're calling that does the check for null checks other conditions as well.
I've dealt with this issue by using a static method to whitelist object calls:
/** Wrapper to mask NullPointerException warnings. */
private static <T> T _(T obj) {
return obj;
}
The method name is intended to not interfere with readability. Thus,
mObject.method();
becomes
_(mObject).method();
Furthermore, if a NullPointerException does occur it will still refer to the same line number.

Mark unit test as an expected failure in JUnit

How can I mark a test as an expected failure in JUnit 4?
In this case I want to continue to run this test until something is patched upstream. Ignoring the test goes a little too far, as then I might forget about it. I may be able to add an #expected annotation and catch the exception thrown by assertThat, but that also seems to lie about the expected behavior.
Here's what my current test looks like:
#Test
public void unmarshalledDocumentHasExpectedValue()
{
doc = unmarshaller.unmarshal(getResourceAsStream("mydoc.xml"));
final ST title = doc.getTitle();
assertThat(doc.getTitle().toStringContent(), equalTo("Expected"));
}
That assert should succeed, but because of an upstream bug it doesn't. Yet, that test is correct; it should succeed. Virtually all the alternatives that I've found are misleading. Right now I think #Ignore("This test should pass once fixed upstream") is my best bet, but I still have to remember to come back to it. I'd prefer that the test run.
In Python I can use the expectedFailure decorator:
class ExpectedFailureTestCase(unittest.TestCase):
#unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
With Qt's QTestLib in C++, you can use QEXPECT_FAIL:
QEXPECT_FAIL("", "Will be fixed next version", Continue);
QCOMPARE(i, 42);
In both cases above, the unit test runs which is what I'm hoping to have happen. Am I missing something in JUnit?
I'm not quite getting the specifics of your scenario, but here's how I generally test for expected failure:
The slick new way:
#Test(expected=NullPointerException.class)
public void expectedFailure() {
Object o = null;
o.toString();
}
for older versions of JUnit:
public void testExpectedFailure() {
try {
Object o = null;
o.toString();
fail("shouldn't get here");
}
catch (NullPointerException e) {
// expected
}
}
If you have a bunch of things that you want to ensure throw an exception, you may also want to use this second technique inside a loop rather than creating a separate test method for each case. If you were just to loop through a bunch of cases in a single method using expected, the first one to throw an exception would end the test, and the subsequent cases wouldn't get checked.
What about explicitly expecting an AssertionError?
#Test(expected = AssertionError.class)
public void unmarshalledDocumentHasExpectedValue() {
// ...
}
If you're reasonably confident that only the JUnit machinery within the test would raise AssertionError, this seems as self-documenting as anything.
You'd still run the risk of forgetting about such a test. I wouldn't let such tests into version control for long, if ever.
I'm assuming here that you want the test to pass if your assert fails, but if the assert succeeds, then the test should pass as well.
The easiest way to do this is to use a TestRule. TestRule gives the opportunity to execute code before and after a test method is run. Here is an example:
public class ExpectedFailureTest {
public class ExpectedFailure implements TestRule {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (Throwable e) {
if (description.getAnnotation(Deprecated.class) != null) {
// you can do whatever you like here.
System.err.println("test failed, but that's ok:");
} else {
throw e;
}
}
}
};
}
}
#Rule public ExpectedFailure expectedFailure = new ExpectedFailure();
// actually fails, but we catch the exception and make the test pass.
#Deprecated
#Test public void testExpectedFailure() {
Object o = null;
o.equals("foo");
}
// fails
#Test public void testExpectedFailure2() {
Object o = null;
o.equals("foo");
}
}
First, note that the first method is marked as #Deprecated. I'm using this as a marker for the method for which I want to ignore any assertion failures. You can do whatever you like to identify the methods, this is just an example.
Next, in the ExpectedFailure#apply(), when I do the base.evaluate(), I'm catching any Throwable (which includes AssertionError) and if the method is marked with the annotation #Deprecated, I ignore the error. You can perform whatever logic you like to decide whether you should ignore the error or not, based on version number, some text, etc. You can also pass a dynamically determined flag into ExpectedFailure to allow it to fail for certain version numbers:
public void unmarshalledDocumentHasExpectedValue() {
doc = unmarshaller.unmarshal(getResourceAsStream("mydoc.xml"));
expectedFailure.setExpectedFailure(doc.getVersionNumber() < 3000);
final ST title = doc.getTitle();
assertThat(doc.getTitle().toStringContent(), equalTo("Expected"));
}
For further examples, see ExternalResource, and ExpectedException
Ignoring an expected failure test rather than passing it
If you want to mark you tests as Ignored rather than Success, it becomes a bit more complex, because tests are ignored before they are executed, so you have to retrospectively mark a test as ignored, which would involve constructing your own Runner. To give you a start, see my answer to How to define JUnit method rule in a suite?. Or ask another question.
One option is mark the test as #Ignore and put text in there that is a bug perhaps and awaiting a fix. That way it won't run. It will then become skipped. You could also make use of the extensions to suit your need in a potentially different way.
I've taken Matthew's answer a step further and actually implemented an #Optional annotation you could use instead of the #Deprecated marker annotation he mentions in his answer. Although simple, I'll share the code with you, maybe it's of help for someone:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface Optional {
/**
* Specify a Throwable, to cause a test method to succeed even if an exception
* of the specified class is thrown by the method.
*/
Class<? extends Throwable>[] exception();
}
With a simple alteration of Matt's ExpectedFailure class:
public class ExpectedFailure implements TestRule {
#Override
public Statement apply(final Statement base, final Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (Throwable e) {
// check for certain exception types
Optional annon = description.getAnnotation(Optional.class);
if (annon != null && ArrayUtils.contains(annon.exception(), e.getClass())) {
// ok
} else {
throw e;
}
}
}
};
}
}
You can now annotate your test method with #Optional and it will not fail, even if the given type of exception is raised (provide one or more types you would like the test method to pass):
public class ExpectedFailureTest {
#Rule public ExpectedFailure expectedFailure = new ExpectedFailure();
// actually fails, but we catch the exception and make the test pass.
#Optional(exception = NullPointerException.class)
#Test public void testExpectedFailure() {
Object o = null;
o.equals("foo");
}
}
[UPDATE]
You could also rewrite your tests using JUnit's org.junit.Assume instead of the tradtional org.junit.Assert, if you want your tests to pass even if the assumption does not hold.
From Assume's JavaDoc:
A set of methods useful for stating assumptions about the conditions in which a test is meaningful.A failed assumption does not mean the code is broken, but that the test provides no useful information. The default JUnit runner treats tests with failing assumptions as ignored.
Assume is available since JUnit 4.4
Use mocked upstream class if possible. Stub it with correct result. Optionally, replace mock with real object after bug is fixed.

Categories