JUnit参数化测试失败。

huangapple go评论90阅读模式
英文:

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&lt;Object[]&gt; urls() {
return List.of(new Object[][]{
{&quot;https://www.google.com/&quot;},
{&quot;...&quot;},
{&quot;...&quot;},
});
}
@Parameterized.Parameter
public String invalidUrl;
@Parameterized.Parameter
public String language;
@Parameterized.Parameter
public String country;
public static Collection&lt;Object[]&gt; invalidUrls() {
return List.of(new Object[][]{
{&quot;https://www.google.com/, &quot;en&quot;, &quot;US&quot;},
{...},
{...}    
});
}
@Before
public void createConnection() {
connection = new Connection();
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws MalformedURLException, URISyntaxException {
Map&lt;String, String&gt; params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, &quot;ru&quot;, &quot;RU&quot;).toString().endsWith(&quot;&amp;hl=en&amp;gl=US&quot;));
}
@Test
public void parameterIdShouldNotBeEmpty() throws MalformedURLException {
Assert.assertFalse(connection.getParameters(url).get(&quot;id&quot;).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&lt;String&gt; urls = List.of(
&quot;some link&quot;,
&quot;some link&quot;
);
private final List&lt;String&gt; invalidUrls = List.of(
&quot;some link&quot;,
&quot;some link&quot;
);
@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, &quot;ru&quot;, &quot;RU&quot;);
}
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws MalformedURLException, URISyntaxException {
for (String url : urls) {
Map&lt;String, String&gt; params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, &quot;ru&quot;, &quot;RU&quot;).toString().endsWith(&quot;&amp;hl=ru&amp;gl=RU&quot;));
Assert.assertTrue(connection.getLocalized(params, &quot;en&quot;, &quot;US&quot;).toString().endsWith(&quot;&amp;hl=en&amp;gl=US&quot;));
}
}
@Test
public void parameterIdShouldNotBeEmpty() throws MalformedURLException {
for (String url : urls) {
Assert.assertFalse(connection.getParameters(url).get(&quot;id&quot;).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 添加索引。

例如,在这里 {&quot;https://www.google.com/, &quot;en&quot;, &quot;US&quot;}, 你有 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 {&quot;https://www.google.com/, &quot;en&quot;, &quot;US&quot;}, 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&lt;Object&gt; urls() {
return List.of(
&quot;https://www.google.com/&quot;,
&quot;...&quot;,
&quot;...&quot;
);
}
@Parameterized.Parameter
public String url;
private Connection connection;
@Before
public void createConnection() {
connection = new Connection();
}
@Test
public void urlShouldBeLocalizedWithRequiredLanguage() throws Exception {
Map&lt;String, String&gt; params = connection.getParameters(url);
Assert.assertTrue(connection.getLocalized(params, &quot;ru&quot;, &quot;RU&quot;).toString().endsWith(&quot;&amp;hl=en&amp;gl=US&quot;));
}
@Test
public void parameterIdShouldNotBeEmpty() throws Exception {
Assert.assertFalse(connection.getParameters(url).get(&quot;id&quot;).isEmpty());
}
}
public static class InvalidUrls {
@Parameterized.Parameters()
public static Object[][] invalidUrls() {
return new Object[][]{
new Object[] {&quot;https://www.google.com/, &quot;en&quot;, &quot;US&quot;},
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"

huangapple
  • 本文由 发表于 2020年8月30日 04:02:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63651269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定