Development Tip

JUnit : @Before 대신 생성자 사용

yourdevel 2020. 11. 14. 11:09
반응형

JUnit : @Before 대신 생성자 사용


JUnit 4를 사용하고 있습니다. 생성자에서 초기화하는 것과 주석이 달린 전용 초기화 함수를 사용하는 것의 차이점을 볼 수 없습니다 @Before. 이것은 내가 그것에 대해 걱정할 필요가 없다는 것을 의미합니까?

@Before생성자에서 초기화하는 것 이상을 제공 하는 경우가 있습니까?


아니요, 생성자를 사용하여 JUnit 테스트 픽스처를 초기화하는 것은 기술적 @Before으로 메서드 를 사용하는 것과 같습니다 (JUnit이 각각에 대해 테스트 클래스의 새 인스턴스를 생성하기 때문에 @Test). 유일한 (connotational) 차이는 대칭의 파괴이다 @Before@After일부 혼동 될 수있다. IMHO (사용하는 @Before) 규칙을 준수하는 것이 좋습니다 .

또한 JUnit 4 및 주석 이전에는 전용 setUp()tearDown()메서드 가있었습니다 . @Before@After주석이이를 대체하지만 기본 로직은 유지합니다. 따라서 주석을 사용하면 JUnit 3 또는 이전 버전에서 마이그레이션하는 사람이 더 쉽게 사용할 수 있습니다.

주목할만한 차이점

댓글에서 더 자세한 정보 :

  • @Before 부모 클래스 동작을 재정의 할 수 있으며 생성자는 부모 클래스 생성자를 호출하도록합니다.
  • 생성자는 하위 클래스 생성자 및 메서드 보다 먼저 실행 되고 모든 생성자 이후@Rule@Before실행됩니다.
  • @Before원인 @After메서드가 호출 되는 동안 예외가 발생 하고 생성자의 예외가 발생하지 않습니다.

@Before는 클래스 생성자 이후에 호출되기 때문에 특정 경우에 사용하는 것이 더 합리적입니다. 이 차이는 @Mock 주석이있는 Mockito와 같은 모의 프레임 워크를 사용할 때 중요합니다. 모의가 초기화 된 후 @Before 메서드가 호출되기 때문입니다. 그런 다음 모의를 사용하여 테스트중인 클래스에 생성자 인수를 제공 할 수 있습니다.

공동 작업 빈을 사용할 때 단위 테스트에서 이것이 매우 일반적인 패턴이라는 것을 알았습니다.

다음은 (인위적인) 예입니다.

@RunWith(MockitoJUnitRunner.class)
public class CalculatorTest {
    @Mock Adder adder;
    @Mock Subtractor subtractor;
    @Mock Divider divider;
    @Mock Multiplier multiplier;

    Calculator calculator;

    @Before
    public void setUp() {
        calculator = new Calculator(adder,subtractor,divider,multiplier);
    }

    @Test
    public void testAdd() {
        BigDecimal value = calculator.add(2,2);
        verify(adder).add(eq(2),eq(2));
    }
}

나는 그것이 나에게 모든 구성원 할 수 있기 때문에 내 테스트 객체를 초기화하는 생성자를 사용하는 것을 선호 final때 IDE 또는 컴파일러 말해됩니다 그래서 생성자는 멤버를 초기화 및 설정에서 다른 방법을 방지하는 것을 잊었다을.

IMHO는 @Before객체를 완전히 초기화하기 위해 생성자에 의존하는 가장 중요한 Java 규칙 중 하나를 위반합니다!


내 조명기를 최종적으로 선언하고 인라인 또는 생성자에서 초기화하는 것을 선호하므로 초기화하는 것을 잊지 않습니다! 그러나 @Before에서 throw 된 예외는보다 사용자 친화적 인 방식으로 처리되기 때문에 일반적으로 @Before에서 테스트중인 개체를 초기화합니다.


@Before는 Test-Class 당 한 번뿐 아니라 @Test보다 먼저 호출됩니다.
이것은 모든 특정 테스트에 대한 데이터를 재설정 / 초기화하는 데 사용할 수 있습니다 (예 : 변수를 특정 값으로 재설정하는 등).

동일한 패션에서 @After를 사용하여 @Test 메서드를 실행 한 후 코드를 정리할 수 있습니다.

참조 : http://junit.sourceforge.net/javadoc/org/junit/Before.html


There is one thing that constructor can archive but not @Before.

You have to use a constructor when you need to initial fields defined in parent class. For example:

abstract class AbstractIT {
   int fieldAssignedInSubClass;
   public AbstractIT(int fieldAssignedInSubClass) {
      this.fieldAssignedInSubClass= fieldAssignedInSubClass;
   }

   @Before
   void before() {
      // comsume fieldAssignedInSubClass
   } 
}

public class ChildIT extends AbstractIT{
   public ChildIT() {
      // assign fieldAssignedInSubClass by constructor
      super(5566); 
   }

   @Before
   void before() {
      // you cannot assign fieldAssignedInSubClass by a @Before method
   } 
}

Quote from http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/

You may be wondering why you should write a setUp( ) method instead of simply initializing fields in a test case's constructor. After all, since a new instance of the test case is created for each of its test methods, the constructor is always called before setUp( ). In a vast majority of cases, you can use the constructor instead of setUp( ) without any side effects.

In cases where your test case is part of a deeper inheritance hierarchy, you may wish to postpone object initialization until instances of derived classes are fully constructed. This is a good technical reason why you might want to use setUp( ) instead of a constructor for initialization. Using setUp( ) and tearDown( ) is also good for documentation purposes, simply because it may make the code easier to read.


@Before does make sense to use for several reasons. It makes your test code more readable. It matches @After annotation which is responsible for releasing used resources and is a counterpart of the @BeforeClass annotation.


There is no difference except that the constructor is the only method ehere can initialize the @Rule objects:

public class TestClass {

    @Rule
    public SomeRule rule;

    public TestClass() {
        // code to initialize the rule field
        conf = new RuleConf()
        rule = new SomeRule(conf)
    }
}

참고URL : https://stackoverflow.com/questions/6094081/junit-using-constructor-instead-of-before

반응형