Mockito @Mock
와 @InjectMocks
주석을 사용하여 Spring으로 주석이 달린 개인 필드에 종속성을 주입합니다 @Autowired
.
@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Mock
private SomeService service;
@InjectMocks
private Demo demo;
/* ... */
}
과
public class Demo {
@Autowired
private SomeService service;
/* ... */
}
이제 실제 객체를 @Autowired
setter없이 개인 필드에 주입하고 싶습니다 . 이것이 가능합니까 아니면 메커니즘은 Mocks 주입에만 국한됩니까?
답변
@Spy
주석 사용
@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Spy
private SomeService service = new RealServiceImpl();
@InjectMocks
private Demo demo;
/* ... */
}
Mockito는 주석으로 주석이 달린 인스턴스에 삽입 될 잠재적 후보로서 모든 필드 @Mock
또는 @Spy
주석을 고려합니다 @InjectMocks
. 위의 경우 'RealServiceImpl'
인스턴스는 ‘데모’에 주입됩니다.
자세한 내용은
답변
@Dev Blanked 응답 추가에서 Spring이 만든 기존 Bean을 사용하려는 경우 코드를 다음과 같이 수정할 수 있습니다.
@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Inject
private ApplicationContext ctx;
@Spy
private SomeService service;
@InjectMocks
private Demo demo;
@Before
public void setUp(){
service = ctx.getBean(SomeService.class);
}
/* ... */
}
이렇게하면 테스트를 수행하기 위해 코드를 변경하거나 다른 생성자를 추가 할 필요가 없습니다.
답변
Mockito는 DI 프레임 워크가 아니며 DI 프레임 워크조차도 필드 주입보다 생성자 주입을 권장합니다.
따라서 테스트중인 클래스의 종속성을 설정하기 위해 생성자를 선언하면됩니다.
@Mock
private SomeService serviceMock;
private Demo demo;
/* ... */
@BeforeEach
public void beforeEach(){
demo = new Demo(serviceMock);
}
spy
일반적인 경우에 Mockito 를 사용 하는 것은 끔찍한 조언입니다. 그것은 테스트 클래스를 직진하지 않고 취하기 쉽고 오류가 발생하기 쉽습니다. 실제로 조롱되는 것은 무엇입니까? 실제로 무엇을 테스트합니까?
@InjectMocks
그리고 @Spy
이 클래스에서 비 대한 클래스와 혼합 책임을 장려하기 때문에 또한 전체 디자인을 아파요.
제발 읽기 spy()
javadoc는 (강조 광산하지 않습니다) 그 맹목적으로 사용하기 전에 :
실제 개체의 스파이를 만듭니다. 스파이 전화 는 스텁되지 않는 한 실제 메소드를 . 실제 스파이는 예를 들어 레거시 코드를 처리 할 때 신중하고 가끔 사용해야합니다 .
평소와 같이
partial mock warning
: 객체 지향 프로그래밍은 복잡성을 별도의 특정 SRPy 객체로 나누어 복잡성을 해결합니다. 부분 모의가이 패러다임에 어떻게 맞습니까? 글쎄, 그것은 단지 … 부분 모의는 복잡성이 동일한 객체에서 다른 방법으로 이동되었음을 의미합니다. 대부분의 경우 이것은 응용 프로그램을 디자인하려는 방식이 아닙니다.그러나 부분 모의가 유용한 경우는 드물다. 코드를 다루기 만하면 쉽게 변경할 수 없다 (타사 인터페이스, 레거시 코드의 중간 리팩토링 등). 그러나 테스트 중심의 새로운 모의를 위해 부분 모의를 사용하지는 않을 것이다. 설계된 코드.
답변
Spring에는 ReflectionTestUtils
이 목적을위한 전용 유틸리티가 있습니다. 특정 예를 들어 현장에 주입하십시오.
@Spy
..
@Mock
..
@InjectMock
Foo foo;
@BeforeEach
void _before(){
ReflectionTestUtils.setField(foo,"bar", new BarImpl());// `bar` is private field
}
답변
나는 이것이 오래된 질문이라는 것을 알고 있지만 문자열을 주입하려고 할 때 같은 문제에 직면했습니다. 그래서 우리는 정확히 원하는 것을 수행하는 JUnit5 / Mockito 확장을 발명했습니다. https://github.com/exabrial/mockito-object-injection
편집하다:
@InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();
@BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}
@AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}