gpt4 book ai didi

java - 如何在不复制代码的情况下测试 Junit5 中接口(interface)的不同实现

转载 作者:行者123 更新时间:2023-11-29 08:23:30 26 4
gpt4 key购买 nike

请问如何为具有不同实现的接口(interface)编写junit 5测试?

比如我有一个接口(interface)Solution,有SolutionISolutionII等不同的实现,是否可以只写一个测试类来测试两者都有?

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

请问有没有像Junit4中使用的优雅方式

在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() {

}
}

Junit 5声称ExtendWith()类似,我试了下面的代码

@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++];
}
}
}

不幸的是,testMethod1 使用的是 SolutionItestMethod2 使用的是 SolutionII,这是有道理的,我不知道不知道这是否有助于激发一点灵感。

提前感谢您的帮助

最佳答案

木星提供 Test interfaces完全符合您的目的 - 测试接口(interface)契约(Contract)

例如,让我们有一个字符串诊断合约的接口(interface)和两个遵循合约但利用不同实现思想的实现:

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);
}
}

根据推荐的方法,您将创建测试接口(interface),以验证default 方法中的诊断契约,并将依赖于实现的部分公开给钩子(Hook):

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"));
}
}

然后为每个特定的解决方案实现此测试接口(interface):

class DefaultDiagnoseTest implements StringDiagnoseTest<DefaultDiagnose> {

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

class StreamBasedDiagnoseTest implements StringDiagnoseTest<StreamBasedDiagnose> {

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

使用更多 Hook 和非默认接口(interface)方法来测试同名解决方案的方面(如性能),并在接口(interface)实现中定义新测试以获得完全不同的实现特性。

关于java - 如何在不复制代码的情况下测试 Junit5 中接口(interface)的不同实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55437810/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com