I'm attempting to write some tests using the built-in android Junit testing framework. I am running into a problem with a test where I am expecting an exception to be thrown. In JUnit, the annotation for the test method would be:
@Test(expected = ArithmeticException.class)
However, in Android, this test fails with an ArithmeticException.
I understand that the Android implementation is only a subset of JUnit 3, and doesn't even allow the annotation @Test (must be @SmallTest, @MediumTest, or @LargeTest, and none of those allow for the 'expected=..' parameter), but this seems like a fairly significant test, and seems like the Android testing framework would be seriously lacking if it did not have this feature.
Note : I tested this by adding the JUnit jar to the project and by adding and the annotations to my test methods. It makes sense to me why the annotations would be completely ignored because the Android framework (runner?) is not looking for that annotation and just ignores it. Basically, I'm just looking for the 'right' way to do this within the framework.
When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare that we expect an exception to be thrown anywhere in the annotated test method. In this example, we've declared that we're expecting our test code to result in a NullPointerException.
Create a java class file named TestRunner. java in C:\>JUNIT_WORKSPACE to execute test case(s). Compile the MessageUtil, Test case and Test Runner classes using javac. Now run the Test Runner, which will run the test cases defined in the provided Test Case class.
In JUnit 5, to write the test code that is expected to throw an exception, we should use Assertions. assertThrows(). In the given test, the test code is expected to throw an exception of type ApplicationException or its subtype. Note that in JUnit 4, we needed to use @Test(expected = NullPointerException.
The JUnit TestRunners will catch the thrown Exception regardless so you don't have to worry about your entire test suite bailing out if an Exception is thrown. This is the best answer.
The standard junit 3 idiom for this sort of test was:
public void testThatMethodThrowsException() { try { doSomethingThatShouldThrow(); Assert.fail("Should have thrown Arithmetic exception"); } catch(ArithmeticException e) { //success } }
Now JUnit4 is available via Android SDK (refer to android-test-kit)
Update: it's official now on d.android.com:
The AndroidJUnitRunner is a new unbundled test runner for Android, which is part of the Android Support Test Library and can be downloaded via the Android Support Repository. The new runner contains all improvements of GoogleInstrumentationTestRunner and adds more features:
- JUnit4 support
- Instrumentation Registry for accessing Instrumentation, Context and Bundle Arguments
- Test Filters @SdkSupress and @RequiresDevice
- Test timeouts
- Sharding of tests
- RunListener support to hook into the test run lifecycle
- Activity monitoring mechanism ActivityLifecycleMonitorRegistry
So, JUnit4 style of exception testing using expected annotation:
@Test(expected= IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
or expected exception rules:
@Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); thrown.expect(IndexOutOfBoundsException.class); thrown.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line }
is also possible.
Refer to official documentation for more details on how to setup test support library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With