[java] Mockito : 개인 @Autowired 필드에 실제 객체 주입

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;

    /* ... */
}

이제 실제 객체를 @Autowiredsetter없이 개인 필드에 주입하고 싶습니다 . 이것이 가능합니까 아니면 메커니즘은 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();
 }


답변