【问题标题】:How to run a generic parameterized JUnit test in Eclipse?如何在 Eclipse 中运行通用参数化 JUnit 测试?
【发布时间】:2016-02-29 19:14:39
【问题描述】:

为了避免简单的集成测试使用大量冗余测试类,我想创建一个参数化的通用测试类,如下例所示:

@RunWith(Parameterized.class)
public class MovementTest<V extends Vehicle, T extends Track<V>> {

    private final V testVehicle;

    private final T testTrack;

    public MovementTest(V vehicle, T track){
        testVehicle = vehicle;
        testTrack = track;
    }

    @Test
    public void testMovement(){
        testVehicle.moveAlong(testTrack);
    }

    @Parameters
    public static Iterable<Object[]> provideTestExamples(){
        Object[][] params = {
            { new Car(), new Highway() },
            { new Train(), new RailRoadTrack() }
        };
        return Arrays.asList(params);
    }
}

public interface Vehicle {
    void moveAlong(Track t);
}

public interface Track<E extends Vehicle> { }    

public class Train implements Vehicle {
    @Override
    public void moveAlong(Track t) {}
}

public class RailRoadTrack implements Track<Train> {}

public class Car implements Vehicle {
    @Override
    public void moveAlong(Track t) { }
}

public class Highway implements Track<Car> {}    

不幸的是,这个测试类是不可运行的。有没有一种简洁的方法来实现类似的东西?

【问题讨论】:

  • 任何堆栈跟踪、日志等?您有 Object[][] 参数,但正在创建新的 Object[]
  • @Gaskoin 已修复。此外,Eclipse 没有提供运行该测试类的选项,因此没有堆栈跟踪。
  • eclipse JUnit 运行器将针对类型擦除的字节码运行,因此 MovementTest 具有通用类型参数并不重要。您使用的是相对较新的 eclipse 版本吗? JUnit 4 在项目路径上吗?我对 Eclipse Luna 中的参数化测试没有任何问题——即使是具有泛型类型参数的测试。
  • @KenKoster 我尝试了 Helios 和 Luna 的结果相同。但事实证明:我太习惯于让 JUnit 运行配置即席可执行文件,因为 IDE 通常会自动创建它们。我忽略的是我可以手动创建运行配置。等等,问题解决了。还是谢谢。

标签: java eclipse generics junit parameterized


【解决方案1】:

#1

您可以使用JUnitParametrized 跑步者。它的工作原理如下:

@RunWith(Parameterized.class)
public class ParametrizedTest {

    private final String text;
    private final int number;

    public ParametrizedTest(String text, int number) {
        this.text = text;
        this.number = number;
    }

    @Test
    public void shouldContainNumber() {
        assertTrue(text.contains(String.valueOf(number)));
    }

    @Parameterized.Parameters
    public static Iterable<Object[]> params() {
        return Arrays.asList(
                new Object[][]{
                        {"test string 1", 1},
                        {"test string 2", 2}
                }
        );
    }
}

您可以阅读有关此解决方案的更多信息here

#2(更好)

使用JUnitParameters (link) 还有更好的方法(我认为是这样),看看吧:

@RunWith(JUnitParamsRunner.class)
public class JUnitParamsTest{

    @Test
    @Parameters
    public void shouldContainNumber(String text, int number) {
        assertTrue(text.contains(String.valueOf(number)));
    }

    public Object[] parametersForShouldContainNumber() {
        return $(
                $("test string 1", 1),
                $("test string 2", 2)
        );
    }
}

请注意,提供参数的方法名称必须适合测试名称。这个解决方案似乎更好,因为(不仅)您在执行后得到更好的测试名称:

[OK] JUnitParams.[0]测试字符串 1, 1 (shouldContainNumber)

[确定] JUnitParams.[1]测试字符串 2, 2 (shouldContainNumber)

可以在项目站点找到更全面的列表,了解为什么它更好:

  • 更明确 - 参数在测试方法参数中,而不是类字段中
  • 更少的代码——你不需要构造函数来设置参数
  • 您可以在一个类中混合使用参数化方法和非参数化方法
  • 参数可以作为 CSV 字符串或从参数提供程序类传递
  • 参数提供者类可以有尽可能多的参数提供方法,以便您可以对不同的情况进行分组
  • 您可以拥有一个提供参数的测试方法(不再需要外部类或静态)
  • 您可以在 IDE 中看到实际的参数值(在 JUnit 的参数化中,它只是连续的参数数量)

【讨论】:

  • 是的,这是一个非常基本的参数化测试,我们经常使用它。但是,这并不能满足我对给定情况的需求。这里的重点是“通用”。
  • 我明天去图书馆看看。乍一看很有希望。谢谢。
【解决方案2】:

我刚刚解决了一个类似的问题,一个具有复杂参数(对象和对象列表的组合)的参数化测试,并且我在此处寻求帮助。

问题中的代码和答案中的代码都应该大致有效。考虑到 Object[][] 可以容纳任何东西,具有更简单类型的示例提供了足够的信息。唯一可能出现的问题是正确声明复杂类型。

我没有使用 Eclipse 运行测试,而是直接使用 Maven。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 2021-09-10
    • 2019-01-30
    • 2012-09-05
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    相关资源
    最近更新 更多