[java] jUnit의 여러 RunWith 문

단위 테스트를 작성 JUnitParamsRunner하고 MockitoJUnitRunner하나의 테스트 클래스 를 사용 하고 싶습니다 .

불행히도 다음은 작동하지 않습니다.

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

하나의 테스트 클래스에서 Mockito와 JUnitParams를 모두 사용하는 방법이 있습니까?



답변

사양에 따라 동일한 주석이 달린 요소에 동일한 주석을 두 번 넣을 수 없기 때문에 이렇게 할 수 없습니다.

그렇다면 해결책은 무엇입니까? 해결책은 @RunWith()당신이 없이는 서있을 수없는 러너와 함께 하나만 놓고 다른 하나를 다른 것으로 교체하는 것입니다. 귀하의 경우에는 제거 MockitoJUnitRunner하고 프로그래밍 방식으로 수행 할 것이라고 생각합니다 .

실제로 실행되는 유일한 작업은 다음과 같습니다.

MockitoAnnotations.initMocks(test);

테스트 케이스의 시작 부분에서. 따라서 가장 간단한 해결책은이 코드를 setUp()메서드에 넣는 것입니다.

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

나는 잘 모르겠지만, 아마도 당신은 플래그를 사용하여이 방법의 여러 호출을 피해야한다 :

private boolean mockInitialized = false;
@Before
public void setUp() {
    if (!mockInitialized) {
        MockitoAnnotations.initMocks(this);
        mockInitialized = true;
    }
}

그러나 더 나은, 재사용 가능한 솔루션은 JUnt의 규칙으로 구현 될 수 있습니다.

public class MockitoRule extends TestWatcher {
    private boolean mockInitialized = false;

    @Override
    protected void starting(Description d) {
        if (!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;
        }
    }
}

이제 테스트 클래스에 다음 줄을 추가하십시오.

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

원하는 러너로이 테스트 케이스를 실행할 수 있습니다.


답변

JUnit 4.7 및 Mockito 1.10.17부터이 기능이 내장되어 있습니다. 이 org.mockito.junit.MockitoRule클래스는. 간단히 가져 와서 라인을 추가 할 수 있습니다.

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

시험 수업에.


답변

이 솔루션은이 mockito 예제뿐만 아니라 가능한 모든 러너에게 적용됩니다. 예를 들면 다음과 같습니다. Spring의 경우 러너 클래스를 변경하고 필요한 주석을 추가하기 만하면됩니다.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

    @Test
    public void subRunner() throws Exception {
        JUnitCore.runClasses(TestMockitoJUnitRunner.class);
    }

    @RunWith(MockitoJUnitRunner.class)
    public static class TestMockitoJUnitRunner {
    }
}

DatabaseModelTestJUnit에서 실행합니다. TestMockitoJUnitRunner(논리에 의해) 그것에 의존 하고 호출하는 동안 메서드 의 메인 내부 에서 실행 됩니다 . 이 방법을 사용하면 하위 실행기가 실행 되기 전에 주 실행기가 올바르게 시작되어 종속 테스트 클래스가있는 여러 중첩 주석을 효과적으로 구현할 수 있습니다.@TestJUnitCore.runClasses(TestMockitoJUnitRunner.class)static class TestMockitoJUnitRunner@RunWith

또한 https://bekce.github.io/junit-multiple-runwith-dependent-tests


답변

PowerMock 1.6이 출시 된 이후로 다음과 같이 쉽게 할 수 있습니다.

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

여기에 설명 https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/


답변

제 경우에는 스프링 빈에서 어떤 방법을 모의하려고했고

MockitoAnnotations.initMocks(test);

작동하지 않습니다. 대신 다음과 같이 xml 파일 내에서 mock 메서드를 사용하여 생성 할 해당 빈을 정의해야합니다.

...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...

다음과 같이 테스트 클래스 내부에 autowired가있는 빈을 추가합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
    ...
    @Autowired
    private ClassWantedToBeMocked classWantedToBeMocked;
    ...
    when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
    ...
}


답변

이 접근 방식을 사용하여 https://bekce.github.io/junit-multiple-runwith-dependent-tests/ 링크를 확인하십시오 . @RunWith (Parameterized.class)-외부 주자-@RunWith (MockitoJUnitRunner.class)- 내부 주자. 내가 추가해야 할 유일한 조정은 내부 / 중첩 된 러너 / 클래스에서 액세스 할 수 있도록 외부 클래스 / 러너의 멤버 변수를 정적으로 만드는 것입니다. 행운을 빕니다.


답변

SWTBotJunit4ClassRunnerorg.junit.runners.Parameterized 를 동시에 실행하고 싶었고 , 파라 메트릭 테스트가 있고 SWT 테스트가 실패 할 때 스크린 샷을 찍고 싶습니다 (스크린 샷 기능은 SWTBotJunit4ClassRunner 에서 제공함 ). @ bekce의 대답은 훌륭하고 먼저 그 경로로 가고 싶었지만 인수를 통과하는 것은 기발했습니다. 또는 하위 클래스에서 매개 변수화를 수행하고 정확한 테스트가 통과 / 실패한 정보를 잃어 버리고 마지막 스크린 샷 만 가지고 있습니다 (스크린 샷 이름이 테스트 자체에서 이름을 가져옴). 그래서 어느 쪽이든 조금 지저분했습니다.

제 경우에는 SWTBotJunit4ClassRunner 가 충분히 간단하므로 클래스의 소스 코드를 복제하고 내 이름을 ParametrizedScreenshotRunner 로 지정했으며 원본이 TestRunner를 확장 한 경우 내 클래스는 Parameterized 클래스를 확장 하므로 본질적으로 내 자신의 러너를 사용할 수 있습니다. 이전 두 개 대신. 내 자신의 러너는 매개 변수화 된 러너 위에 확장되고 그 위에 스크린 샷 기능을 구현합니다. 이제 내 테스트에서는이 “하이브리드”러너를 사용하고 모든 테스트가 예상대로 작동합니다 (테스트 내부에서 아무것도 변경할 필요 없음).

다음과 같은 모습입니다 (간결성을 위해 목록에서 모든 주석을 제거했습니다).

package mySwtTests;

import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;

public class ParametrizedScreenshotRunner extends TestRu Parameterized {

    public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
        super(klass);
    }

    public void run(RunNotifier notifier) {
        RunListener failureSpy = new ScreenshotCaptureListener();
        notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
        notifier.addListener(failureSpy);
        try {
            super.run(notifier);
        } finally {
            notifier.removeListener(failureSpy);
        }
    }
}