Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @BeforeClass和继承-执行顺序_Java_Unit Testing_Testng - Fatal编程技术网

Java @BeforeClass和继承-执行顺序

Java @BeforeClass和继承-执行顺序,java,unit-testing,testng,Java,Unit Testing,Testng,我有一个抽象基类,用作单元测试的基础(TestNG 5.10)。在这个类中,我为我的测试初始化了整个环境,设置了数据库映射等。这个抽象类有一个带有@BeforeClass注释的方法来进行初始化 接下来,我用特定的类扩展该类,在这些类中我有@Test方法和@BeforeClass方法。这些方法执行特定于类的环境初始化(例如,将一些记录放入数据库) 如何强制执行带注释方法的@BeforeClass的特定顺序?我需要先执行抽象基类中的,然后执行扩展类中的 例如: abstract class A {

我有一个抽象基类,用作单元测试的基础(TestNG 5.10)。在这个类中,我为我的测试初始化了整个环境,设置了数据库映射等。这个抽象类有一个带有
@BeforeClass
注释的方法来进行初始化

接下来,我用特定的类扩展该类,在这些类中我有
@Test
方法和
@BeforeClass
方法。这些方法执行特定于类的环境初始化(例如,将一些记录放入数据库)

如何强制执行带注释方法的
@BeforeClass
的特定顺序?我需要先执行抽象基类中的,然后执行扩展类中的

例如:

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @BeforeClass
    doSpecificInitialization() {...}

    @Test
    doTests() {...}
}
预期订单:

A.doInitialization
B.doSpecificInitialization
B.doTests
实际订单:

B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization        // <---not executed
 B.doTests)                // <-/

B.doSpecificationInitialization/不要将
@BeforeClass
放在
抽象类上。从每个子类调用它

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

似乎TestNG已经-尝试一下。

编辑:下面的答案是针对JUnit的,但我还是把它留在这里,因为它可能会有所帮助

根据:“超类的@BeforeClass方法将在当前类的方法之前运行。”

我测试了这个,它似乎对我有效


然而,正如@Odys在下面提到的,对于JUnit,您需要以不同的方式命名两个方法,尽管这样做只会导致运行子类方法,因为父类将被隐藏。

我刚刚用5.11尝试了您的示例,我首先调用了基类的@BeforeClass

您可以发布testng.xml文件吗?可能您在那里同时指定了A和B,而只有B是必需的

请随时关注testng用户邮件列表,我们可以更仔细地查看您的问题

--
Cedric

让@BeforeClass方法调用一个空的specificBeforeClass()方法,该方法可以被子类覆盖,也可以不被子类覆盖,如下所示:

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}

我向抽象类添加了
public
,TestNG(6.0.1)在
doTests
之前执行doInitialization()。如果我从类A中删除
public
,TestNG不会执行
doInitialization()

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}

当我从运行时:JUnitCore.runClasses(TestClass.class) 它将在子级之前正确执行父级(您不需要super.SetUpBeforeClass();) 如果从Eclipse运行它: 由于某种原因,它无法运行基类。 解决办法: 明确地调用基类:(BaseTest.setUpBeforeClass();) 如果从应用程序运行基类,您可能希望在基类中有一个标志,以确定它是否已经设置好。因此,如果您通过这两种可能的方法运行它,那么它只运行一次(例如从eclipse进行个人测试,通过ANT进行构建版本)


这似乎是Eclipse的一个bug,或者至少是意外的结果。

在我的例子(JUnit)中,基类和派生类中有相同的方法setup()。在这种情况下,只调用派生类的方法,我让它调用基类方法

为什么不尝试在超类中创建一个抽象方法doSpecialInit(),从超类中的BeforeClass注释方法调用它呢


因此继承您的类的开发人员被迫实现这个方法。

我刚刚讨论了这个问题,并找到了另一种实现方法。只需在抽象类中的
@BeforeClass
@beforethod
上使用
alwaysRun
,即可正常工作

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}

可以使用
dependsOnMethod

e、 g.如果是弹簧(
AbstractTestNGSpringContextTests


使用继承实现此目的的更好、更干净的方法可能如下所示-

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

对于JUnit: 正如@fortega所提到的: 根据JUnitAPI:“超类的@BeforeClass方法将在当前类的方法之前运行。”


但是要小心,不要用相同的名称命名这两个方法。因为在这种情况下,父方法将被子-父方法隐藏

这里还有另一个简单的解决方案

我的特殊情况是,我需要在执行超类中的“BeforeClass”之前,从子类中的“BeforeClass”注入模拟服务

为此,只需在子类中使用
@ClassRule

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
例如:

@ClassRule
public static ExternalResource mocksInjector = new ExternalResource() {
    @Override
    protected void before() {
        // inject my mock services here
        // Note: this is executed before the parent class @BeforeClass
    }
};

我希望这有帮助。这可以有效地以“反向”顺序执行静态设置。

检查导入语句。 应该是

import org.testng.annotations.BeforeClass

不是


import org.junit.BeforeClass

我今天遇到了类似的问题,唯一的区别是基类不是抽象的

这是我的箱子

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    private void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}
类a中的
@BeforeClass
方法从未执行过

  • A.doInitialization()->此操作从未以静默方式执行
  • B.剂量规格初始化()
  • B.doTests()
通过使用隐私修饰符,我发现如果从类继承器看不到方法,TestNG将不会执行继承类中带注释的
@BeforeClass
方法

因此,这将起作用:

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
    protected void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}
因此,会发生以下情况:

  • A.初步化()
  • B.剂量规格初始化()
  • B.doTests()
    • 这对我很有用--


      这基本上就是我想要避免的:不需要显式调用超级(抽象)类的方法。特别是我还有一些类,它们继承自一个,但没有自己的@BeforeClass方法。我只需要插入一个就可以了。
      dependsOnMethods
      解决方法解决了这个问题。虽然我更喜欢“超类优先”的方法……但使用“dependsOnMethod”时,“doInitialization”不应该用“@Test”来表示吗?我
      abstract class A {
          @BeforeClass
          doInitialization() {...}
      }
      
      class B extends A {
          @Override
          @BeforeClass
          doInitialization() { 
      
             //do class specific init
      
          }   
      
          @Test
          doTests() {...}
      }