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

在JUnit5中,我如何从扩展调用测试类方法?

翁鸿远
2023-03-14

在JUnit5中,我试图获得一个从扩展运行的测试类方法。我正在使用JUnit5扩展接口TestWatcher,并重写testFailed()方法。

这个扩展的目的是在测试类的Selenium WebDriver浏览器中拍摄失败的屏幕快照,并将其附加到该测试的诱惑报告中。test class方法有实例化的浏览器和注释,用于附加到Allure。并且我的takeScreenshot方法依赖浏览器和来自测试类的testName字符串来正确运行。

package utils;

public class ScreenshotOnFailureExtension implements TestWatcher{
    @Override
    public void testFailed(ExtensionContext context, Throwable cause) {
        try {
            Object clazz = context.getRequiredTestInstance();
            Method takeScreenshot = clazz.getClass().getMethod("takeScreenshot");
            takeScreenshot.setAccessible(true);
            Object test = clazz.getClass().getConstructor().newInstance();
            takeScreenshot.invoke(test);
        } catch (Exception e) {
            e.printStackTrace();
        } 
}

我的测试类中的代码是这样的:

package tests;

@ExtendWith(ScreenshotOnFailureExtension.class)
public class MyTest implements Config {
    public WebDriver driver;
    public String testName;

//bunch of Junit5 annotations with functions to initialize above variables omitted...

    //take a screen shot
    public void takeScreenshot() {
        System.out.println("Taking screenshot.");
        byte[] srcFile=((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
        saveScreenshot(srcFile, testName+ ".png");
    }
    
    //this attaches screenshot to an allure test result
    @Attachment(value = "{testName}", type = "image/png")
    public byte[] saveScreenshot(byte[] screenShot, String testName) {
        System.out.println("Attaching screenshot to Allure report");
        return screenShot;
    }
}

上面的测试类能够在测试方法中从@aftereach调用时正确拍摄屏幕快照。但我只想在失败的时候接受它。

当我运行测试时,它调用takeScreenshot,但在执行时给出一个异常

正在获取Screenshot.java.lang.Reflect.InvocationTargetException

null

您可以看到我的日志记录语句在该方法中的下一行代码(引用测试实例中的驱动程序)导致的NullPointerException之前输出。有没有正确的方法在上下文中触发现有测试实例的TakesCreenShot()方法?

如果有更简单的方法直接在测试的@aftereach方法中拍摄失败时的屏幕快照,请告诉我。似乎是一个非常基本的用例。:)

共有2个答案

齐嘉庆
2023-03-14

您不应该在扩展中实例化测试类,框架应该负责所有的事情。

请参考文档中的https://junit.org/junit5/docs/current/user-guide/#extensions 5.9.1,并查看此问答

您可以使用它,也可以修改您的TestWatcher以按照注释中的建议执行屏幕截图。您必须将驱动程序引用保存在ExtensionContext中才能访问它。

宗沛
2023-03-14

IMO问题就在你所描述的流程中。JUnit为每个测试方法创建一个测试类的新实例(尽管这是可以更改的)。

更好的方法是:

  1. 使扩展“有状态”,因为它将包含对web驱动程序的引用。
  2. 不要在测试中实现TakesCreenShot方法,而是在扩展(私有方法)中实现
  3. 在扩展中实现回调,并将WebDriver的实例“注入”(通过反射)到测试中,如果您需要在测试中使用它。这将保证测试使用正确实例化的“状态”(webdriver的实例)运行。
  4. 在扩展中实现了“如果测试方法失败,则调用扩展的私有方法TakesCreenShot
  5. ”的逻辑
 类似资料:
  • 问题内容: 我在一个模块中有一个测试类,该模块在其依赖项模块之一中扩展了另一个测试类。如何将依赖项的测试代码导入到依赖模块的测试范围中? 首先,我有两个模块,“ module-one”是对“ module-two”的依赖。是的子类。 但是构建失败了,因为没有将“模块一”的测试代码导入到“模块二”中,而只是将其导入到主代码中。 问题答案: 通常,除了常规的modulename.jar文件之外,还可以

  • 问题内容: 有人可以告诉我如何在Kotlin中对扩展功能进行单元测试吗?由于它们是静态解析的,应该将它们作为静态方法调用还是作为非静态方法进行测试?另外,由于语言可以与Java完全互操作,因此应如何针对Kotlin扩展功能执行Java单元测试? 问题答案: 好吧,要测试一种方法(无论是否静态),您可以像实际代码那样调用它,并检查它是否做对了。 例如,假设此扩展方法在文件com / foo / Ba

  • 有人能告诉我该如何在Kotlin中对扩展函数进行单元测试吗?由于它们是静态解析的,应该将它们测试为静态方法调用还是非静态方法调用?另外,由于语言与Java是完全可互操作的,那么应该如何执行Kotlin扩展函数的Java单元测试呢?

  • JUnit5API中有几个可用的扩展点。 null 我可以使用相同的模式,因为上的可见性。 下面有几个具体的例子来演示: > 基于系统属性启用测试的。这可以通过一些反射和使用或样式的进行测试,但是当并行测试执行时,处理起来似乎更加复杂,可能会出现问题。此示例展示了“如何提供实际的并对结果进行断言”的示例。 扩展测试的自定义测试引擎是正确的方法吗? 那么,如何测试各种扩展实现而不依赖于内部API,并

  • 问题内容: 我有两节课:和。后者声明为: 我需要的只是类中的方法(仅在其中,因为会有很多继承的类,而且我不想在所有这些类中都实现此方法),它将从静态调用返回类名。这是我在说的: 当我称它为: 但是父类中的每个声明只能访问父类变量,该变量的值为“ Action”。 有什么可行的方法吗? 问题答案: 总是返回使用该类的类的名称,因此使用静态方法并没有太大帮助。如果该方法不是静态的,则可以简单地使用ge

  • 如何使用JUnit5测试抛出NullPointerException的方法。但是我在方法中捕获到了这个异常,因此test以错误结尾:“Expected java.lang.NullPointerException to be thrown,But nothing was thrown”。 谢谢