是否可以使JUnit5扩展实现扩展类可以实现的接口?

时间:2019-10-30 19:56:03

标签: java junit5

我想写一个JUnit5 Extension来扩展我的测试课,

@ExtendWith(MyExtension.class)
public class MyTestClass {

  @Test myTest1() {}

  @Test myTest2() {}

  // ...
}

但是,我的测试类也实现了特定的接口,因此看起来更像这样:

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

如何设置我的课程来实现这一目标? (或者,反对这样做的固有缺陷或代码气味是什么?)

2 个答案:

答案 0 :(得分:1)

您需要使用@RegisterExtension批注,该批注允许您手动构建扩展实例。

  

通过@ExtendWith声明性地注册扩展名时,它可以   通常只能通过注释进行配置。相反,当   扩展名通过@RegisterExtension注册,可以配置   以编程方式-例如,为了将参数传递给   扩展程序的构造函数,静态工厂方法或构建器API。

听起来SomeClient是从其他地方提供的(也许像Spring这样的DI),但是您需要在MyExtension中使用它。假定这种情况,您可以从类似以下内容开始:

@ExtendWith(SpringExtension.class)
public class MyTestClass {
  @Autowired SomeClient someClient;
  @RegisterExtension
  MyExtension myExtension = new MyExtension(someClient);
}

答案 1 :(得分:1)

一种实现方法是在上下文对象上使用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());
            }
        });
    }
}

在这里您可以看到两件事:

  1. 可能没有测试实例对象,例如在BeforeAllCallback中使用,因为通常是根据测试创建测试实例。
  2. 需要强制转换。这意味着您应该检查您的测试实例是否确实实现了SomeInterface

话虽如此,我不太确定为什么你要走那条相当复杂的路线。 MyExtension应该从什么中抽象出来?