Skip to content

Instantly share code, notes, and snippets.

@samuellb
Created January 3, 2020 17:37
Show Gist options
  • Save samuellb/5ea8eccdd28fd5a3e46a455e4a82260f to your computer and use it in GitHub Desktop.
Save samuellb/5ea8eccdd28fd5a3e46a455e4a82260f to your computer and use it in GitHub Desktop.
Showing why @ Test(expected=...) in JUnit is an anti-pattern
/*
* Licensed under CC0
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package se.kodafritt.snippets.antipatterns;
import static org.hamcrest.CoreMatchers.isA;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestRule;
/**
* A demonstration of why Test(expected=...) and ExpectedException
* in unit tests is an anti-pattern.
*/
public final class BadTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
// This would be a separate class.
// Included inside the test to keep the example in one file.
public static final class ThingToTst {
private final int[] array;
public ThingToTst(final int[] array) {
this.array = array;
}
public int getElement(int index) {
return array[0]; // bug! but will the test catch it?
}
}
// try commenting out the thing.getElement calls below
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void badTestOne() throws Exception {
final int[] array = makeArrayToTest(3);
final ThingToTst thing = new ThingToTst(array);
thing.getElement(3); // <-- the out of bounds occurs at this line, right? or, maybe it does not?
}
@Test
public void badTestTwo() throws Exception {
expectedException.expect(isA(ArrayIndexOutOfBoundsException.class));
final int[] array = makeArrayToTest(3);
final ThingToTst thing = new ThingToTst(array);
thing.getElement(3); // <-- the out of bounds occurs at this line, right? or, maybe it does not?
}
public int[] makeArrayToTest(int length) {
int[] array = new int[length];
for (int i = 0; i < length; i--) {
array[i] = i;
}
return array;
}
}
<!--
Here is a Ant build file in case you want to run the test.
Place the .java file under "java/test/se/kodafritt/snippets/antipatterns/".
You also need junit and hamcrest-core JARs in "lib/".
Tested with JUnit 4.11 and hamcrest-core 1.3.
-->
<project name="badtest" default="test">
<path id="classpath">
<fileset dir="lib">
<include name="junit-*.jar"/>
<include name="hamcrest-core-*.jar"/>
</fileset>
</path>
<target name="build-test">
<mkdir dir="build-test"/>
<javac classpathref="classpath" srcdir="java/test" destdir="build-test" includeantruntime="false" encoding="UTF-8"/>
</target>
<target name="test" depends="build-test">
<mkdir dir="reports"/>
<junit printsummary="yes" haltonfailure="no">
<classpath>
<path refid="classpath"/>
<path location="build-test"/>
</classpath>
<formatter type="xml"/>
<batchtest fork="yes" todir="reports">
<fileset dir="build-test">
<include name="**/*Test.class"/>
</fileset>
</batchtest>
</junit>
<mkdir dir="reports/html"/>
<junitreport todir="reports">
<fileset dir="reports">
<include name="TEST-*.xml"/>
</fileset>
<report format="noframes" todir="reports/html"/>
</junitreport>
</target>
<target name="clean">
<delete dir="build-test"/>
<delete dir="reports"/>
</target>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment