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

j2qf4p5b  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(95)

下面的示例测试生成如下所示的输出。
样品测试:

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;

class OuterTest
{

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

字符串
输出量:

outerSetup
 outerTest1
outerTearDown
outerSetup
 outerTest2
outerTearDown
outerSetup
 innerSetup
  innerRepeatedTest
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerRepeatedTest
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerRepeatedTest
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerParameterizedTest - foo
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerParameterizedTest - bar
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerParameterizedTest - baz
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerTest1
 innerTearDown
outerTearDown
outerSetup
 innerSetup
  innerTest2
 innerTearDown
outerTearDown


对于我们的用例,我们希望实现的是,@BeforeEach/@AfterEach方法只在OuterTest类中的每个测试之前/之后以及第一个**之前被调用。在类InnerTest中的最后一次测试之后,**但不在内部类的测试之间。
因此,所需的输出如下:

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


我试图通过实现一个扩展来改变@BeforeEach/@AfterEach方法的行为,该扩展实现了一个InvocationInterceptor,但我未能发现测试类是否是内部类中的最后一个测试,这将使我能够决定是否应该调用外部类的@BeforeEach/@AfterEach方法。
有人知道如何实现这一点吗?
提前感谢!

iszxjhcz

iszxjhcz1#

如果你能够提取你实际的外部setup和teardown方法,你可以为外部测试引入第二个@Nested类,然后使用@BeforeAll@AfterAll调用外部setup/teardown一次:

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

相关问题