多次测试只执行一次初始化代码 类

Executing Initialization Code only once for multiple test classes

我正在为我的代码编写单元测试用例。我将 PowerMockito 与 Junit 一起使用。我已经编写了一个初始化代码,它将处理我应用程序中的所有初始化内容。以下是我的代码的结构方式:

Class ServiceInitializer{
    public static isInitialized = Boolean.FALSE;

    public static void initialize(){
        //Initilization Code Goes Here
        isInitialized = Boolean.TRUE;
    }
}

@RunWith(PowerMockRunner.class)
class BaseTest{

    @Before
    public void preTest(){
        //some code
    }


    static{
        if(!ServiceInitializer.isInitialized){
            ServiceInitializer.initialize();
        }
    }

    @After
    public void postTest(){
        //some code
    }
}

public TestClass1 extends BaseTest{
    @Test
    public void testMethodA_1(){//test code}

    @Test
    public void testMethodA_2(){//test code}

    @Test
    public void testMethodA_3(){//test code}
}

public TestClass2 extends BaseTest{
    @Test
    public void testMethodB_1(){//test code}

    @Test
    public void testMethodB_2(){//test code}

    @Test
    public void testMethodB_3(){//test code}
}

我正在使用 Junit 和 batchtest 目标将这些测试用例作为 ant 脚本执行,如下所示:

<junit printsummary="yes" haltonfailure="yes" showoutput="yes">
            <classpath refid="JUnitTesting.classpath"/>
            <batchtest haltonerror="false" haltonfailure="no" todir="${junit.output.dir}/raw">
                <formatter type="plain"/>
                <formatter type="xml"/>     
                <fileset dir="${basedir}/src">
                  <include name="**/Test*.java"/>
                </fileset>
            </batchtest>
        </junit>

我能够很好地执行测试用例,但是它的初始化代码写在 BaseTest class 的静态块中,这给我带来了问题。每当 New Test Class 开始执行时,每次都会调用 "ServiceInitializer.initialize();"。所以,如果我有 10 个 Test Classes 那么这个方法就会被调用 10 次。我想控制它,无论我有多少 Test Classes,它都只执行一次。我怎样才能做到这一点? JUnit 甚至可以做到这一点吗?

--更新--

我知道有 @BeforeClass 注释可用,它为每个测试 class 只执行一次代码块。但这并没有满足我的要求,因为一旦 JUnit 运行另一个测试 class,它就会调用“@BeforeClass”注释下的方法,并再次运行初始化代码,尽管在那里进行了初始化检查。

您可以在 JUnit 中使用 @BeforeClass 注释。

将执行一次测试 class (BaseTest)。

您甚至不需要 'public static isInitialized = Boolean.FALSE;'。 相信 JUnit。 :)

到运行在所有测试class之前,你必须创建一个测试套件并在测试套件class中使用@ClassRule

尝试@BeforeClass 在每个 class 中只进行一次设置,而不是在每次测试之前进行一次。

PowerMockRunner 在通过标准 classloader 加载测试 class 后安装自己的 classloader。 最好在由

注释的 public 静态方法中执行静态初始化器
@BeforeClass

顺便说一句:除非您在测试 class 级别需要 @PrepareForTest 注释,否则没有必要 运行 使用 PowerMockRunner 进行测试。

考虑在您的 ant-junit 任务中使用 forkmode 元素。默认值为 "perTest":它为每个测试创建一个新的 JVM class。如果您将 forkmode 定义为 "perBatch",则只有一个 JVM 用于您的批处理。所以你的 ServiceInitializer class 保持初始化状态。

另见 the help for junit task here

您可以使用 class 规则:

public class ServiceInitializer extends ExternalResource {
  public static final TestRule INSTANCE = new ServiceInitializer();
  private final AtomicBoolean started = new AtomicBoolean();

  @Override protected void before() throws Throwable {
    if (!started.compareAndSet(false, true)) {
      return;
    }
    // Initialization code goes here
  }

  @Override protected void after() {
  }
}

然后您可以通过使用 @ClassRule 注释在您的测试中使用它:

@RunWith(PowerMockRunner.class)
class BaseTest{
  @Rule
  public PowerMockRule powerMockRule = new PowerMockRule();
  @ClassRule
  public static final TestRule serviceInitializer = ServiceInitializer.INSTANCE;

  @Before
  public final void preTest() {
    // some code
  }

  @After
  public final void postTest() {
    //some code
  }
}

编辑: PowerMockRunner 显然不支持@ClassRule,所以我将测试切换为使用PowerMockRule。您可以从 here 阅读更多相关信息。无论如何,我个人更喜欢规则而不是自定义跑步者。