如何在内部(嵌套)类的测试之间抑制外部类的 @BeforeEach 和 @AfterEach 方法的执行

问题描述 投票:0回答:1

以下示例测试生成如下打印的输出。

样品测试:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class OuterTest extends ParentTest implements TestInterface1, TestInterface2
{
   @BeforeEach
   void outerSetup()
   {
      System.out.println( " outerSetup" );
   }


   @AfterEach
   void outerTearDown()
   {
      System.out.println( " outerTearDown" );
   }


   @Test
   void outerTest1()
   {
      System.out.println( "  outerTest1" );
   }


   @Test
   void outerTest2()
   {
      System.out.println( "  outerTest2" );
   }

   @Nested
   class InnerTest
   {
      @BeforeEach
      void innerSetup()
      {
         System.out.println( "  innerSetup" );
      }


      @AfterEach
      void innerTearDown()
      {
         System.out.println( "  innerTearDown" );
      }


      @Test
      void innerTest1()
      {
         System.out.println( "   innerTest1" );
      }


      @Test
      void innerTest2()
      {
         System.out.println( "   innerTest2" );
      }


      @RepeatedTest(3)
      void innerRepeatedTest()
      {
         System.out.println( "   innerRepeatedTest" );
      }


      @ParameterizedTest
      @ValueSource(strings = { "foo", "bar", "baz" })
      void innerParameterizedTest( final String input )
      {
         System.out.println( "   innerParameterizedTest - " + input );
      }
   }
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;

public class ParentTest
{
   @BeforeEach
   void parentSetup()
   {
      System.out.println( "parentSetup" );
   }


   @AfterEach
   void parentTearDown()
   {
      System.out.println( "parentTearDown" );
   }

}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;

public interface TestInterface1
{
   @BeforeEach
   default void interface1Setup()
   {
      System.out.println( "interface1Setup" );
   }


   @AfterEach
   default void interface1TearDown()
   {
      System.out.println( "interface1TearDown" );
   }
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;

public interface TestInterface2
{
   @BeforeEach
   default void interface2Setup()
   {
      System.out.println( "interface2Setup" );
   }


   @AfterEach
   default void interface2TearDown()
   {
      System.out.println( "interface2TearDown" );
   }
}

输出:

parentSetup
interface1Setup
interface2Setup
 outerSetup
  outerTest1
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  outerTest2
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerRepeatedTest
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerRepeatedTest
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerRepeatedTest
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerParameterizedTest - foo
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerParameterizedTest - bar
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerParameterizedTest - baz
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerTest1
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerTest2
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown

对于我们的用例,我们希望实现,

@BeforeEach
/
@AfterEach
方法仅在类
OuterTest
中的每个测试之前/之后调用,以及在第一个之前调用。 在类中的最后一个测试之后
InnerTest
但不在内部类的测试之间。

所以期望的输出如下:

parentSetup
interface1Setup
interface2Setup
 outerSetup
  outerTest1
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  outerTest2
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown
parentSetup
interface1Setup
interface2Setup
 outerSetup
  innerSetup
   innerRepeatedTest
  innerTearDown
  innerSetup
   innerRepeatedTest
  innerTearDown
  innerSetup
   innerRepeatedTest
  innerTearDown
  innerSetup
   innerParameterizedTest - foo
  innerTearDown
  innerSetup
   innerParameterizedTest - bar
  innerTearDown
  innerSetup
   innerParameterizedTest - baz
  innerTearDown
  innerSetup
   innerTest1
  innerTearDown
  innerSetup
   innerTest2
  innerTearDown
 outerTearDown
interface1TearDown
interface2TearDown
parentTearDown

我尝试通过实现扩展来更改

@BeforeEach
/
@AfterEach
方法的行为,该扩展实现了
InvocationInterceptor
,但我无法确定测试类是否是内部类中的最后一个测试,这将导致能够决定是否应该调用外部类的
@BeforeEach
/
@AfterEach
方法。

有谁知道如何实现这一目标?

提前致谢!

java junit junit5 junit5-extension-model
1个回答
0
投票

如果您能够提取实际的外部设置和拆卸方法,则可以为外部测试引入第二个

@Nested
类,并使用
@BeforeAll
@AfterAll
调用外部设置/拆卸一次:

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class OuterTest {

    void actualOuterSetUp() {
        System.out.println("outerSetUp");
    }

    void actualOuterTearDown() {
        System.out.println("outerTearDown");
    }

    @Nested
    class InnerTestA {

        @BeforeEach
        void outerSetUp() {
            actualOuterSetUp();
        }


        @AfterEach
        void outerTearDown() {
            actualOuterTearDown();
        }

        @Test
        void outerTest1() {
            System.out.println(" outerTest1");
        }

        @Test
        void outerTest2() {
            System.out.println(" outerTest2");
        }

    }

    @Nested
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    class InnerTestB {

        @BeforeAll
        void outerSetUp() {
            actualOuterSetUp();
        }

        @AfterAll
        void outerTearDown() {
            actualOuterTearDown();
        }

        @BeforeEach
        void innerSetUp() {
            System.out.println(" innerSetUp");
        }


        @AfterEach
        void innerTearDown() {
            System.out.println(" innerTearDown");
        }


        @Test
        void innerTest1() {
            System.out.println("  innerTest1");
        }


        @Test
        void innerTest2() {
            System.out.println("  innerTest2");
        }

        @RepeatedTest(3)
        void innerRepeatedTest() {
            System.out.println("  innerRepeatedTest");
        }

        @ParameterizedTest
        @ValueSource(strings = {"foo", "bar", "baz"})
        void innerParameterizedTest(final String input) {
            System.out.println("  innerParameterizedTest - " + input);
        }

    }

}

输出(嵌套类的顺序可能因系统而异):

outerSetUp
 outerTest1
outerTearDown
outerSetUp
 outerTest2
outerTearDown
outerSetUp
 innerSetUp
  innerRepeatedTest
 innerTearDown
 innerSetUp
  innerRepeatedTest
 innerTearDown
 innerSetUp
  innerRepeatedTest
 innerTearDown
 innerSetUp
  innerParameterizedTest - foo
 innerTearDown
 innerSetUp
  innerParameterizedTest - bar
 innerTearDown
 innerSetUp
  innerParameterizedTest - baz
 innerTearDown
 innerSetUp
  innerTest1
 innerTearDown
 innerSetUp
  innerTest2
 innerTearDown
outerTearDown

如果您使用的是 Java 16+,您还可以省略

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
并使用
static
代替。

© www.soinside.com 2019 - 2024. All rights reserved.