In our current project we are using Robolectric when writing unit tests for our Android application and it has been working out really well. Recently I needed to write a test case that performed an operation several times, but with different test data, and assert that the correct actions occurred depending on the data.
JUnit has an easy to use option for this called Parameterized testing where one defines the test data and then uses the Parameterized test runner to execute the test. This will create one instance of the test class for each element of test data with the data being passed to the constructor.
As it turns out, Robolectric has a ParameterizedRobolectricTestRunner, which is exactly the same thing (but slightly tweaked to conform with Robolectric) and worked very well for my test that verifies the app behaviour for different error codes received from an external service provider.
@RunWith(ParameterizedRobolectricTestRunner.class) public class ContactServiceTest { @ParameterizedRobolectricTestRunner.Parameters(name = "ErrorCode = {0}") public static Collection
This will execute the test case six times, once for each element of test data, and compare the displayed error message to the error message defined for the specific error code. Each test run will be treated as its own test case as the report is created.
Adding the name
parameter to the Parameters annotation will tidy up the test results. As the results for the test run are displayed, the name of the test case will in this case be
when_known_error_code_is_received_from_service_correct_error_msg_is_displayed_to_user[ErrorCode = 105] when_known_error_code_is_received_from_service_correct_error_msg_is_displayed_to_user[ErrorCode = 113] when_known_error_code_is_received_from_service_correct_error_msg_is_displayed_to_user[ErrorCode = 114] ...
For further inspiration checkout JUnit Theories and also junit-quickcheck, a great way to generate the test data in your JUnit (and therefore also Robolectric) test, instead of defining it yourself.
I find when I use a data type such as an enum as a test argument, I get this error:
java.lang.IllegalArgumentException: argument type mismatch
My code, modified from yours:
@RunWith(ParameterizedRobolectricTestRunner.class)
public final
class ContactServiceTest {
public
enum ErrorCode {
AAA,
BBB,
CCC
}
@ParameterizedRobolectricTestRunner.Parameters(name = “ErrorCode = {0}”)
public static
Collection data() {
return Arrays.asList(new Object[][]{
// {105, “105_ERROR_MSG”},
// {113, “113_ERROR_MSG”},
// {999, “DEFAULT_ERROR_MSG”}
{ErrorCode.AAA, “105_ERROR_MSG”},
{ErrorCode.BBB, “113_ERROR_MSG”},
{ErrorCode.CCC, “DEFAULT_ERROR_MSG”}
});
}
private int errorCode;
private String expectedErrorMsg;
public
ContactServiceTest(ErrorCode errorCode, String errorMsg) {
// this.errorCode = errorCode;
// this.expectedErrorMsg = errorMsg;
}
@Test
public
void testRobolectricTestWithData() {
}
}
Pingback: itemprop="name">unit testing - How to run @RunWith(RobolectricTestRunner::class) and @RunWith(Parameterized::class) together in Junit4 - Code Utility - Code Utility