英文:
JUnit parameterized test failed
问题
我刚刚开始使用JUnit(之前阅读了一些文章),遇到了问题。我有一个参数化测试类:
@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);
}
}
我会得到以下异常:
@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)
...
....
还有一些关于 Parameter(1) 没有使用的异常。
以及一些 Parameter(2,3) 的异常。
总结:4个测试全部失败。甚至没有正确的测试数量。
或者我应该放弃参数化测试,改用:
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());
}
}
}
最后这个变体运行得很好,但是关于参数化情况呢?我真的不想在每个方法中使用 for 循环。
英文:
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.
答案1
得分: 1
你需要将这个测试分成两个带参数的测试。
据我所知,只能有一个数据列表 - 只能有一个 @Parameterized.Parameters
。
一个用于正常的 URL,另一个用于无效的。
在无效的测试中,你需要将 invalidUrls()
标记为 @Parameterized.Parameters
。
此外,你必须给 @Parameterized.Parameter
添加索引。
例如,在这里 {"https://www.google.com/, "en", "US"},
你有 3 个参数。
因此,你必须使用
@Parameterized.Parameter(0) // 零是默认值,不是必需的
public String invalidUrl;
@Parameterized.Parameter(1)
public String language;
@Parameterized.Parameter(2)
public String country;
英文:
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;
答案2
得分: 0
你可以使用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);
}
}
}
更多选项请参考这里。
英文:
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"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论