是否可以使 JUnit5 扩展实现由扩展 class 实现的接口?
Is it possible to make a JUnit5 Extension implement an interface that is fulfilled by the extended class?
我想写一个 JUnit5 Extension 来扩展我的测试 class,
@ExtendWith(MyExtension.class)
public class MyTestClass {
@Test myTest1() {}
@Test myTest2() {}
// ...
}
不过,我的测试class也实现了某个接口,所以看起来更像这样:
public interface SomeInterface {
SomeClient getSomeClient();
SomeClient getSomeClientAsAdministrator();
}
@ExtendWith(MyExtension.class)
public class MyTestClass implements SomeInterface {
@Test myTest1() {}
@Test myTest2() {}
// ...
SomeClient getSomeClient() {
// ...
}
SomeClient getSomeClientAsAdministrator() {
// ...
}
}
目前没有任何谜团。
但是现在,我希望这些接口实现也可用于扩展,例如
public class MyExtension implements BeforeEachCallback, SomeInterface
{
@Override
public void beforeAll(ExtensionContext extensionContext) {
// be able to use getSomeClient();
}
}
如何设置我的 classes 以实现此目的? (或者,反对这样做的固有缺陷或代码味道是什么?)
您需要使用允许您手动构建扩展实例的 @RegisterExtension
注释。
When an extension is registered declaratively via @ExtendWith, it can
typically only be configured via annotations. In contrast, when an
extension is registered via @RegisterExtension, it can be configured
programmatically — for example, in order to pass arguments to the
extension’s constructor, a static factory method, or a builder API.
听起来 SomeClient
是从其他地方提供的(可能是像 Spring 的 DI),但你需要它在 MyExtension
中。假设这种情况,您可以从以下内容开始:
@ExtendWith(SpringExtension.class)
public class MyTestClass {
@Autowired SomeClient someClient;
@RegisterExtension
MyExtension myExtension = new MyExtension(someClient);
}
实现此目的的一种方法是在上下文对象上使用 getTestInstance()
:
public class MyExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
context.getTestInstance().ifPresent(instance -> {
if (instance instanceof SomeInterface) {
SomeInterface some = (SomeInterface) instance;
System.out.println(some.getSomeClient());
}
});
}
}
这里可以看到两件事:
- 可能没有测试实例对象,例如在
BeforeAllCallback
中,因为通常每个测试都会创建测试实例。
- 需要演员表。这意味着您应该检查您的测试实例是否真的实现了
SomeInterface
话虽如此,我不太确定您为什么要走那条相当复杂的路线。 MyExtension
应该抽象出什么?
我想写一个 JUnit5 Extension 来扩展我的测试 class,
@ExtendWith(MyExtension.class)
public class MyTestClass {
@Test myTest1() {}
@Test myTest2() {}
// ...
}
不过,我的测试class也实现了某个接口,所以看起来更像这样:
public interface SomeInterface {
SomeClient getSomeClient();
SomeClient getSomeClientAsAdministrator();
}
@ExtendWith(MyExtension.class)
public class MyTestClass implements SomeInterface {
@Test myTest1() {}
@Test myTest2() {}
// ...
SomeClient getSomeClient() {
// ...
}
SomeClient getSomeClientAsAdministrator() {
// ...
}
}
目前没有任何谜团。
但是现在,我希望这些接口实现也可用于扩展,例如
public class MyExtension implements BeforeEachCallback, SomeInterface
{
@Override
public void beforeAll(ExtensionContext extensionContext) {
// be able to use getSomeClient();
}
}
如何设置我的 classes 以实现此目的? (或者,反对这样做的固有缺陷或代码味道是什么?)
您需要使用允许您手动构建扩展实例的 @RegisterExtension
注释。
When an extension is registered declaratively via @ExtendWith, it can typically only be configured via annotations. In contrast, when an extension is registered via @RegisterExtension, it can be configured programmatically — for example, in order to pass arguments to the extension’s constructor, a static factory method, or a builder API.
听起来 SomeClient
是从其他地方提供的(可能是像 Spring 的 DI),但你需要它在 MyExtension
中。假设这种情况,您可以从以下内容开始:
@ExtendWith(SpringExtension.class)
public class MyTestClass {
@Autowired SomeClient someClient;
@RegisterExtension
MyExtension myExtension = new MyExtension(someClient);
}
实现此目的的一种方法是在上下文对象上使用 getTestInstance()
:
public class MyExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
context.getTestInstance().ifPresent(instance -> {
if (instance instanceof SomeInterface) {
SomeInterface some = (SomeInterface) instance;
System.out.println(some.getSomeClient());
}
});
}
}
这里可以看到两件事:
- 可能没有测试实例对象,例如在
BeforeAllCallback
中,因为通常每个测试都会创建测试实例。 - 需要演员表。这意味着您应该检查您的测试实例是否真的实现了
SomeInterface
话虽如此,我不太确定您为什么要走那条相当复杂的路线。 MyExtension
应该抽象出什么?