Reputation: 746
I've just started with JUnit (read some articles before) and met problem. I've a parameterized test class:
@RunWith(value = Parameterized.class)
public class ConnectionTest {
private Connection connection;
@Parameterized.Parameter
public String url;
@Parameterized.Parameters()
public static Collection<Object[]> urls() {
return List.of(new Object[][]{
{"https://www.google.com/"},
{"..."},
{"..."},
});
}
@Parameterized.Parameter
public String invalidUrl;
@Parameterized.Parameter
public String language;
@Parameterized.Parameter
public String country;
public static Collection<Object[]> invalidUrls() {
return List.of(new Object[][]{
{"https://www.google.com/, "en", "US"},
{...},
{...}
});
}
@Before
public void createConnection() {
connection = new Connection();
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws MalformedURLException, URISyntaxException {
Map<String, String> params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, "ru", "RU").toString().endsWith("&hl=en&gl=US"));
}
@Test
public void parameterIdShouldNotBeEmpty() throws MalformedURLException {
Assert.assertFalse(connection.getParameters(url).get("id").isEmpty());
}
@Test(expected = InvalidGooglePlayGameUrlException.class)
public void notValidUrlShouldThrowException() throws InvalidUrlException, URISyntaxException, MalformedURLException {
connection.connect(invalidUrl, language, country);
}
}
I'll get following Exception:
@Parameter(0) is used more than once (4).
java.lang.Exception: @Parameter(0) is used more than once (4).
at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.validateFields(BlockJUnit4ClassRunnerWithParameters.java:119)
...
....
And
@Parameter(1) is never used.
java.lang.Exception: @Parameter(1) is never used.
And some for Parameter(2,3).
Summary: 4 tests, all failed. Not even proper number of tests.
Or should I just left Parameterized tests and go with:
public class ConnectionTest {
private Connection connection;
private final List<String> urls = List.of(
"some link",
"some link"
);
private final List<String> invalidUrls = List.of(
"some link",
"some link"
);
@Before
public void createConnection() {
connection = new Connection();
}
@Test(expected = InvalidUrlException.class)
public void invalidUrlShouldThrowException() throws InvalidUrlException, URISyntaxException, MalformedURLException {
for (String url : invalidUrls) {
connection.connect(url, "ru", "RU");
}
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws MalformedURLException, URISyntaxException {
for (String url : urls) {
Map<String, String> params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, "ru", "RU").toString().endsWith("&hl=ru&gl=RU"));
Assert.assertTrue(connection.getLocalized(params, "en", "US").toString().endsWith("&hl=en&gl=US"));
}
}
@Test
public void parameterIdShouldNotBeEmpty() throws MalformedURLException {
for (String url : urls) {
Assert.assertFalse(connection.getParameters(url).get("id").isEmpty());
}
}
}
Last variant works fine, but what about parameterized case? I don't really want to use for loops in each method.
Upvotes: 1
Views: 1386
Reputation: 24520
You could structure your test with the Enclosed runner.
@RunWith(Enclosed.class)
public class TestClass {
@RunWith(Parameterized.class)
public static class ValidUrls {
@Parameterized.Parameters()
public static Collection<Object> urls() {
return List.of(
"https://www.google.com/",
"...",
"..."
);
}
@Parameterized.Parameter
public String url;
private Connection connection;
@Before
public void createConnection() {
connection = new Connection();
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws Exception {
Map<String, String> params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, "ru", "RU").toString().endsWith("&hl=en&gl=US"));
}
@Test
public void parameterIdShouldNotBeEmpty() throws Exception {
Assert.assertFalse(connection.getParameters(url).get("id").isEmpty());
}
}
public static class InvalidUrls {
@Parameterized.Parameters()
public static Object[][] invalidUrls() {
return new Object[][]{
new Object[] {"https://www.google.com/, "en", "US"},
new Object[] {...},
new Object[] {...}
});
}
@Parameterized.Parameter(0)
public String invalidUrl;
@Parameterized.Parameter(1)
public String language;
@Parameterized.Parameter(2)
public String country;
private Connection connection;
@Before
public void createConnection() {
connection = new Connection();
}
@Test(expected = InvalidGooglePlayGameUrlException.class)
public void notValidUrlShouldThrowException() throws Exception {
connection.connect(invalidUrl, language, country);
}
}
}
For more options have a look at "Excluding a non param test in parameterized test class"
Upvotes: 0
Reputation: 2934
You need to split this test into two parameterized tests.
As far as I know there can be only one list of data - only one @Parameterized.Parameters
One for nornal urls and one for invalid.
In invalid test you need to mark invalidUrls()
as @Parameterized.Parameters
Additionally you must add indexes to @Parameterized.Parameter
For example here {"https://www.google.com/, "en", "US"},
you have 3 parameters.
Thus you must use
@Parameterized.Parameter(0) // zero is default and not required
public String invalidUrl;
@Parameterized.Parameter(1)
public String language;
@Parameterized.Parameter(2)
public String country;
Upvotes: 1