모의 개체-MockIto Initialising
많은 방법 모의 개체 MockIto을 사용하여 초기화하기 위한 것.이 중에서 무엇이 최선의 방법?
1.
public class SampleBaseTestCase {
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
@RunWith(MockitoJUnitRunner.class)
mock(XXX.class);
만약 어떤 다른 새로운 방법보다 낫다 날을 제시해 보시오...
그 모크스 초기화하려면 주자 또는을 사용하여.MockitoAnnotations.initMocks
니 엄격하게 등가 해결책입니다.그 Mockito의 javadoc부터.JUnitRunner:
그래서 MockitoAnnotations.initMocks(Object)의 명확한 사용할 필요는 없다JUnit 45선수 모크스 모의와 주석이 달린 초기화합니다.Mocks 각 시험 법 전에 초기화됩니다.
번째 해결 방법(「」를 ).MockitoAnnotations.initMocks
러너( 「러너」)가 이미 되어 있는 할 수 .SpringJUnit4ClassRunner
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
해결 (「」를 사용).MockitoJUnitRunner
)가 더 내가 가장 좋아하는 명작이야.이 코드가 더 간단하다.Runner를 사용하면 프레임워크 사용 현황을 자동으로 확인할 수 있는 큰 이점이 있습니다(이 답변에서는 @David Wallace에 의해 설명됨).
두 솔루션 모두 테스트 방법 간에 모크(및 스파이)를 공유할 수 있습니다.와 조합하면 유닛테스트를 매우 빠르게 작성할 수 있습니다.보일러 플레이트 모킹 코드가 줄어들어 테스트 판독이 쉬워집니다.예를 들어 다음과 같습니다.
@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock(name = "database") private ArticleDatabase dbMock;
@Spy private UserProvider userProvider = new ConsumerUserProvider();
@InjectMocks private ArticleManager manager;
@Test public void shouldDoSomething() {
manager.initiateArticle();
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
manager.finishArticle();
verify(database).removeListener(any(ArticleListener.class));
}
}
장점: 코드는 최소입니다.
단점: 흑마법.IMO는 주로 @InjectMocks 주석 때문입니다.이 주석과 함께 "코드의 고통을 덜어줍니다" (@Brice의 훌륭한 코멘트 참조)
세 번째 해결책은 각 테스트 방법에 대한 모의실험을 만드는 것입니다.답변에서 @mlk에 설명된 대로 "self contained test"를 가질 수 있습니다.
public class ArticleManagerTest {
@Test public void shouldDoSomething() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
장점: API가 어떻게 동작하는지를 명확하게 보여주고 있다(BDD...)
단점: 보일러 플레이트 코드가 더 있습니다.(모크 작성)
제가 추천하는 것은 타협입니다.를 사용합니다.@Mock
를 사용한 @RunWith(MockitoJUnitRunner.class)
, ,는 @InjectMocks
:
@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Spy private UserProvider userProvider = new ConsumerUserProvider();
@Test public void shouldDoSomething() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
장점: API가 어떻게 동작하는지 명확하게 설명합니다(How my my my my my my my my )ArticleManager
인스턴스화 됩니다).보일러 플레이트 코드는 없습니다.
단점: 테스트가 자체 억제되지 않고 코드의 번거로움이 줄어듭니다.
현재(v1.10.7 현재) Mock을 인스턴스화하는 네 번째 방법은 MockitoRule이라고 불리는 JUnit4 규칙을 사용하고 있습니다.
@RunWith(JUnit4.class) // or a different runner of your choice
public class YourTest
@Rule public MockitoRule rule = MockitoJUnit.rule();
@Mock public YourMock yourMock;
@Test public void yourTestMethod() { /* ... */ }
}
JUnit은 @Rule로 주석을 단 TestRule의 서브클래스를 검색하여 Runner가 제공하는 테스트 문을 래핑합니다.결과적으로 @Before 메서드, @After 메서드를 추출할 수 있습니다.또한 규칙에 래퍼를 캐치할 수도 있습니다.테스트 내에서 예상한 방식으로 이러한 항목과 상호 작용할 수도 있습니다.예외는 그렇다.
Mockito Rule은 Mockito와 거의 똑같이 동작합니다.JUnitRunner는 파라미터화(테스트 컨스트럭터가 여러 번 테스트를 실행할 수 있도록 인수를 사용할 수 있음)나 Robollectric의 테스트 러너(클래스로더가 Android 네이티브클래스를 대체할 Java를 제공할 수 있음)와 같은 다른 어떤 러너도 사용할 수 있습니다.따라서 최신 JUnit 및 Mockito 버전에서 사용할 수 있는 유연성이 대폭 향상되었습니다.
요약:
Mockito.mock()
: 또는 직접 주석 지원이나 사용 검증 없이 직접 호출합니다.MockitoAnnotations.initMocks(this)
지원, 석석지 、 용용검검없없 。MockitoJUnitRunner
: 주석 지원 및 사용 검증. 단, 해당 주자를 사용해야 합니다.MockitoRule
: JUnit Runner 입니다.
다음 항목도 참조하십시오.JUnit @Rule의 구조
Mockito Annotations & Runner는 위에서 충분히 논의되었으므로, 저는 사랑받지 못하는 사람들을 위해 기부하겠습니다.
XXX mockedXxx = mock(XXX.class);
이 테스트를 사용하는 이유는 좀 더 알기 쉽기 때문입니다.또한 (적절한 금지 사항이 아닌) 단위 테스트에서는 멤버 변수를 사용하지 않는 것이 좋습니다.테스트는 가능한 한 멤버 변수를 스스로 억제하는 것이 좋습니다.
이것을 하는 깔끔한 방법이 있다.
유닛 테스트의 경우는, 다음과 같이 실시할 수 있습니다.
@RunWith(MockitoJUnitRunner.class) public class MyUnitTest { @Mock private MyFirstMock myFirstMock; @Mock private MySecondMock mySecondMock; @Spy private MySpiedClass mySpiedClass = new MySpiedClass(); // It's gonna inject the 2 mocks and the spied object per reflection to this object // The java doc of @InjectMocks explains it really well how and when it does the injection @InjectMocks private MyClassToTest myClassToTest; @Test public void testSomething() { } }
편집: 통합 테스트인 경우 이 작업을 수행할 수 있습니다(스프링에서는 이 방법으로 사용할 수 없습니다).다른 러너로 모크를 초기화할 수 있다는 것을 보여주기만 하면 됩니다).
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("aplicationContext.xml") public class MyIntegrationTest { @Mock private MyFirstMock myFirstMock; @Mock private MySecondMock mySecondMock; @Spy private MySpiedClass mySpiedClass = new MySpiedClass(); // It's gonna inject the 2 mocks and the spied object per reflection to this object // The java doc of @InjectMocks explains it really well how and when it does the injection @InjectMocks private MyClassToTest myClassToTest; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } @Test public void testSomething() { } }
JUnit 5 Jupiter의 경우 "RunWith"가 제거되었습니다. 이제 "@ExtendWith" 주석을 사용하여 Extensions를 사용해야 합니다.
@ExtendWith(MockitoExtension.class)
class FooTest {
@InjectMocks
ClassUnderTest test = new ClassUnderTest();
@Spy
SomeInject bla = new SomeInject();
}
1. Mockito Annotations.open Mocks() 사용:
MockitoAnnotations.initMock()
되고 Mockito 2로 됩니다.MockitoAnnotations.openMocks()
' 3요.3'입니다.MockitoAnnotations.openMocks()
는 메서드의 합니다.AutoClosable
테스트 후 리소스를 닫는 데 사용할 수 있습니다.은 '보다 낫다'를 사용한 입니다.MockitoAnnotations.openMocks()
.
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
class MyTestClass {
AutoCloseable openMocks;
@BeforeEach
void setUp() {
openMocks = MockitoAnnotations.openMocks(this);
// my setup code...
}
@Test
void myTest() {
// my test code...
}
@AfterEach
void tearDown() throws Exception {
// my tear down code...
openMocks.close();
}
}
2. @ExtendWith(MockitoExtension.class) 사용:
JUnit5 @RunWith
을 사용하다은 '보다 낫다'를 사용한 입니다.@ExtendWith
:
@ExtendWith(MockitoExtension.class)
class MyTestClass {
@BeforeEach
void setUp() {
// my setup code...
}
@Test
void myTest() {
// my test code...
}
@AfterEach
void tearDown() throws Exception {
// my tear down code...
}
}
의 " " "Mockito
그 방법은 폐지되었다.
권장되는 방법은 사용입니다.
MockitoJUnitRunner
또는 을 위해JUnit4
MockitoExtension
을 위해서JUnit5
MockitoTestNGListener
을 위해서TestNG
전용 러너/내선번호를 사용할 수 없는 경우 사용할 수 있습니다.
기타 답변은 훌륭하며, 필요한 경우 자세한 내용이 포함되어 있습니다.
그 외에 TL을 추가하고 싶습니다.DR:
- 사용하는 것을 선호하다
@RunWith(MockitoJUnitRunner.class)
- (이미 다른 주자를 사용하고 있기 때문에) 사용할 수 없는 경우
@Rule public MockitoRule rule = MockitoJUnit.rule();
- (2)와 비슷하지만 더 이상 사용하지 마십시오.
@Before public void initMocks() { MockitoAnnotations.initMocks(this); }
- 하나의 테스트에서만 모형을 사용하고 동일한 테스트 클래스의 다른 테스트에 노출하지 않으려면 다음과 같이 하십시오.
X x = mock(X.class)
(1) 및 (2) 및 (3)은 상호 배타적이다.
(4)는 다른 것과 조합하여 사용할 수 있다.
언급URL : https://stackoverflow.com/questions/15494926/initialising-mock-objects-mockito
'programing' 카테고리의 다른 글
Laravel / Vue: v-model 사용 시 검증 중 (0) | 2022.08.12 |
---|---|
사용자 지정 Bootstrap-Vue 확인란 구성 요소 (0) | 2022.08.12 |
Vue.js: 변경 시 호출 함수 (0) | 2022.08.12 |
Java에서 반복적으로 디렉토리 삭제 (0) | 2022.08.12 |
C/C++에서 NULL 포인터를 확인하는 중입니다. (0) | 2022.08.12 |