Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice for multiple Parameterized JUnit Tests

Often, a Java class has more than one public method that we want to test with JUnit. What happens when both public methods are something we can use Parameterized techniques?

Should we keep a JUnit Test class for each public method we want to test with Parameterized parameters, or how do we keep both in one JUnit Test class?

Sample Parameterized JUnit Test class for testing the public method RegionUtils.translateGeographicalCity(...)

@RunWith(Parameterized.class)
public class RegionUtilsTest {
    private String geographicalCity;
    private String expectedAwsRegionCode;

    public RegionUtilsTest(final String geographicalCity,
            final String expectedAwsRegionCode) {
        this.geographicalCity = geographicalCity;
        this.expectedAwsRegionCode = expectedAwsRegionCode;
    }

    @Parameters(name = "translateGeographicalCity({0}) should return {1}")
    public static Collection geographicalCityToAwsRegionCodeMapping() {
        // geographical city, aws region code
        return Arrays.asList(new Object[][] { { "Tokyo", "ap-northeast-1" },
                { "Sydney", "ap-southeast-2" },
                { "North Virginia", "us-east-1" }, { "Oregan", "us-west-2" },
                { "N.California", "us-west-1" }, { "Ireland", "eu-west-1" },
                { "Frankfurt", "eu-central-1" }, { "Sao Paulo", "sa-east-1" },
                { "Singapore", "ap-southeast-1" } });
    }

    @Test
    public void translateGeographicalCityShouldTranslateToTheCorrectAwsRegionCode() {
        assertThat(
                "The AWS Region Code is incorrectly mapped.",
                expectedAwsRegionCode,
                equalTo(RegionUtils.translateGeographicalCity(geographicalCity)));
    }

    @Test(expected = NamedSystemException.class)
    public void translateGeographicalCityShouldThroughAnExceptionIfTheGeographicalCityIsUnknown() {
        final String randomGeographicalCity = RandomStringUtils
                .randomAlphabetic(10);

        RegionUtils.translateGeographicalCity(randomGeographicalCity);
    }
}
like image 993
Oh Chin Boon Avatar asked Feb 21 '15 13:02

Oh Chin Boon


1 Answers

layout: remember you don't do 'class testing', you do 'unit testing'. organize and name your tests in a meaningful way that won't surprise any future readers of your code. usually it means testing all simple methods in one test class, using one or two parameterized tests for each. but sometimes one method is complicated and requires much more detailed testing and then it may be a good idea to create a dedicated test file for it

tools: you need some kind of data providers. then usually each test has its own data providers. sometimes multiple methods can share the same data provider. Sadly, JUnit sucks on that field. recently appeared some libraries extending the JUnit. also JUnit on its own is adding @Parameterized, @Theories etc., but still - it sucks. so if you can't switch to TestNG or Spock try these:

  • if you know all your parameters upfront, check https://github.com/piotrturski/zohhak
  • if you need to read from file and or build data dynamically, check https://github.com/TNG/junit-dataprovider or https://github.com/Pragmatists/JUnitParams
like image 55
piotrek Avatar answered Oct 04 '22 20:10

piotrek