当前位置: 首页 > 知识库问答 >
问题:

如何在Junit5中测试接口的不同实现而不重复代码

宇文念
2023-03-14

例如,我有一个接口solution,有不同的实现,比如solutionisolutionii,我可以只编写一个测试类来测试这两个吗?

有一篇文章展示了一个例子,但是如果有多个测试方法需要调用,我必须为每个测试方法传递参数。

我可以问一下,是否有一种像Junit4中使用的优雅的方法

@RunWith(Parameterized.class)
public class SolutionTest {
  private Solution solution;

  public SolutionTest(Solution solution) {
    this.solution = solution;
  }

  @Parameterized.Parameters
  public static Collection<Object[]> getParameters() {
    return Arrays.asList(new Object[][]{
        {new SolutionI()},
        {new SolutionII()}
    });
  }
  // normal test methods
  @Test
  public void testMethod1() {

  }
}
@ExtendWith(SolutionTest.SolutionProvider.class)
public class SolutionTest {
  private Solution solution;

  public SolutionTest(Solution solution) {
    System.out.println("Call constructor");
    this.solution = solution;
  }

  @Test
  public void testOnlineCase1() {
    assertEquals(19, solution.testMethod(10));
  }

  @Test
  public void testOnlineCase2() {
    assertEquals(118, solution.testMethod(100));
  }

  static class SolutionProvider implements ParameterResolver {
    private final Solution[] solutions = {
        new SolutionI(),
        new SolutionII()
    };
    private static int i = 0;

    @Override
    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
      return parameterContext.getParameter().getType() == Solution.class;
    }

    @Override
    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
      System.out.println(i);
      return solutions[i++];
    }
  }
}

提前感谢您的帮助

共有1个答案

东郭阳德
2023-03-14

Jupiter提供测试接口正是为了您的目的--测试接口契约。

例如,让我们有一个用于字符串诊断契约的接口,以及遵循该契约的两个实现,但使用了不同的实现思想:

public interface StringDiagnose {
    /**
     * Contract: a string is blank iff it consists of whitespace chars only
     * */
    boolean isTheStringBlank(String string);
}

public class DefaultDiagnose implements StringDiagnose {

    @Override
    public boolean isTheStringBlank(String string) {
        return string.trim().length() == 0;
    }
}

public class StreamBasedDiagnose implements StringDiagnose {

    @Override
    public boolean isTheStringBlank(String string) {
        return string.chars().allMatch(Character::isWhitespace);
    }
}

根据推荐的方法,您将创建测试接口,该接口验证default方法中的诊断协定,并向钩子公开与实现相关的片段:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;

public interface StringDiagnoseTest<T extends StringDiagnose> {

    T createDiagnose();

    @Test
    default void blankCheckFollowsContract(){
        assertTrue(createDiagnose().isTheStringBlank("\t\n "));
        assertFalse(createDiagnose().isTheStringBlank("\t\n !  \r\n"));
    }
}
class DefaultDiagnoseTest implements StringDiagnoseTest<DefaultDiagnose> {

    @Override
    public DefaultDiagnose createDiagnose() {
        return new DefaultDiagnose();
    }
}

class StreamBasedDiagnoseTest implements StringDiagnoseTest<StreamBasedDiagnose> {

    @Override
    public StreamBasedDiagnose createDiagnose() {
        return new StreamBasedDiagnose();
    }
}
 类似资料:
  • 我有简单的测试 为什么maven和intellij不能执行Junit5测试?这方面的工作是什么?surefire版本应该已经支持JUnit5测试。

  • 在JUnit 4中,通过使用注释很容易跨一堆类测试不变量。关键是一组测试正在针对单个参数列表运行。 如何在JUnit 5中复制这一点,而不使用JUnit-vintage? 不适用于测试类。听起来可能是合适的,但该注释的目标也是一个方法。 此类 JUnit 4 测试的一个示例是:

  • 我有一个包含所有学生姓名的表,另一个包含学生姓名及其班级注册情况的表,我想显示两个学生的班级名称,即使他们没有注册任何班级,我在注册和未注册之间使用了union唯一的问题是姓名重复 学生(student_id、student_name、专业、级别、年龄) 入学人数(student_id、class_name、学期) 下面是我的 SQL 查询: 选择student_name,class_name从学

  • 如何区分模拟不同的impl类,从而调用impl类的方法。我应该像下面这样做吗。 对我没有用。任何一个都抛出空指针异常。请指教。

  • 我有一个在kotlin的‘基地’项目配置与gradle DSL。在基我有模块'app'和模块'library'。模块应用程序使用模块库。我想从模块应用程序的测试(准确地说是库的testUtils包)访问模块库的测试。 我还检查了代码所在的问题: 我需要在库的源代码中添加,这样在应用程序的测试中,我就可以使用库的测试包,而在应用程序的源代码中,我就不能使用库的测试了。 谢谢你。