봄콩에 모키토 모크 주입
JUnit는 봄콩(3+) 모키토입니다.나의 콩 의존관계는 현재 를 사용하여 주입되고 있습니다.@Autowired
이치노
나는 그것을 사용하는 것을 고려했다.ReflectionTestUtils.setField
그러나 삽입하는 빈 인스턴스는 실제로 프록시이므로 타깃클래스의 개인 멤버필드는 선언되지 않습니다.종속성에 대한 퍼블릭세터를 만들고 싶지 않습니다.이는 순전히 테스트 목적으로 인터페이스를 변경하기 때문입니다.
Spring 커뮤니티의 조언을 몇 가지 따르긴 했지만 모크가 생성되지 않고 자동 배선이 실패합니다.
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
현재 발생한 오류는 다음과 같습니다.
...
Caused by: org...NoSuchBeanDefinitionException:
No matching bean of type [com.package.Dao] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {
@org...Autowired(required=true),
@org...Qualifier(value=dao)
}
at org...DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(D...y.java:901)
at org...DefaultListableBeanFactory.doResolveDependency(D...y.java:770)
★★★★★★★★★★★★★★★를 설정하면,constructor-arg
invalid 에러가 하지 않는 contextvalue to invalid something 입니다.
가장 좋은 방법은 다음과 같습니다.
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
콘텍스트 파일에서 이 모의는 종속된 자동 입력 필드가 선언되기 전에 나열되어야 합니다.
@InjectMocks
private MyTestObject testObject;
@Mock
private MyDependentObject mockedObject;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
그러면 조롱된 개체가 테스트 클래스에 주입됩니다.이 경우 discured Object를 test Object에 주입합니다.이것은 위에서 언급되었지만, 여기 코드가 있습니다.
Spring Java Config와 Mockito를 사용하는 매우 간단한 솔루션이 있습니다.
@Configuration
public class TestConfig {
@Mock BeanA beanA;
@Mock BeanB beanB;
public TestConfig() {
MockitoAnnotations.initMocks(this); //This is a key
}
//You basically generate getters and add @Bean annotation everywhere
@Bean
public BeanA getBeanA() {
return beanA;
}
@Bean
public BeanB getBeanB() {
return beanB;
}
}
지정:
@Service
public class MyService {
@Autowired
private MyDAO myDAO;
// etc
}
자동 배선을 통해 테스트 중인 클래스를 로드하고 Mockito에서 종속성을 모의한 다음 Spring's Reflection을 사용할 수 있습니다.TestUtils: 테스트 중인 클래스에 모크를 주입합니다.
@ContextConfiguration(classes = { MvcConfiguration.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
@Autowired
private MyService myService;
private MyDAO myDAOMock;
@Before
public void before() {
myDAOMock = Mockito.mock(MyDAO.class);
ReflectionTestUtils.setField(myService, "myDAO", myDAOMock);
}
// etc
}
4.3.1 이전 Spring 4.3.1」로 이 붙어 @Transactional
, 「」Cacheable
예를 들어)를 참조해 주세요.이 문제는 SPR-14050에 의해 해결되었습니다.
이전 버전에서는 다음과 같이 프록시의 래핑을 해제하는 것이 해결책입니다.트랜잭션 주석을 통해 서비스가 조롱당하는 것을 피할 수 있습니다(즉,ReflectionTestUtils.setField
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」
스프링 부츠 1.4 spring spring ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」 브랜드만 하세요.@SpringBootTest
의 수업과@MockBean
필드 및 Spring Boot에서는 이러한 유형의 모크가 생성되어 (원래를 삽입하지 않고) 컨텍스트에 삽입됩니다.
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
@MockBean
private RemoteService remoteService;
@Autowired
private Reverser reverser;
@Test
public void exampleTest() {
// RemoteService has been injected into the reverser bean
given(this.remoteService.someCall()).willReturn("mock");
String reverse = reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
}
}
한편, Spring Boot을 사용하지 않거나 이전 버전을 사용하는 경우에는 작업을 좀 더 해야 합니다.
작성하다@Configuration
콩:
@Configuration
@Profile("useMocks")
public class MockConfigurer {
@Bean
@Primary
public MyBean myBeanSpy() {
return mock(MyBean.class);
}
}
「」를 사용합니다.@Primary
수식자가 지정되지 않은 경우 이 콩이 우선임을 봄에게 알리는 주석입니다.
.@Profile("useMocks")
어떤 학급이 진짜 콩을 사용할지, 어떤 학급이 진짜 콩을 사용할지 통제하기 위해서입니다.
에서, 「」, 「」를 액티브하게 .userMocks
★★★★★★★★★★★★★★★★★★:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class})
@WebIntegrationTest
@ActiveProfiles(profiles={"useMocks"})
public class YourIntegrationTestIT {
@Inject
private MyBean myBean; //It will be the mock!
@Test
public void test() {
....
}
}
콩을 useMocks
★★★★★★★★★★★★★★★★★★:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class})
@WebIntegrationTest
public class AnotherIntegrationTestIT {
@Inject
private MyBean myBean; //It will be the real implementation!
@Test
public void test() {
....
}
}
1.8.3 모키토는@InjectMocks
이 돼요 - 정말 도움이 돼요.는 JUnit입니다.@RunWith
MockitoJUnitRunner
나는 ★★★★★★★★★★★★★★★★★★★★@Mock
대상 에게 '''가 부가되어 있을 때 모두 됩니다.프라이빗 멤버에 주석을 달 때 모두 삽입됩니다.@InjectMocks
.
I @RunWith
SpringJUnit4Runner
현재 통합 테스트만 가능합니다.
할 수 것 .List<T>
이치노'모크'를 만족하는 '' .List
mock는객 객체 객체 객입 습않 않않 mock않.으로는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★@Spy
수동으로 인스턴스화된 목록과 대조하여 장치 테스트를 위해 수동으로 .모크 개체를 목록에 추가합니다.의도적이었는지도 모릅니다. 왜냐하면 그것은 분명 제가 함께 조롱당하고 있는 것에 주의를 기울이도록 했기 때문입니다.
업데이트: 이 문제에 대한 보다 나은, 보다 깔끔한 해결책이 제공되었습니다.다른 답변들을 먼저 고려해주세요.
나는 마침내 그의 블로그에서 로넨의 답을 찾았다.가 안고 있던 이 입니다.Mockito.mock(Class c)
「」의 선언Object
따라서 스프링은 공장법 반품 유형에서 콩 유형을 추론할 수 없습니다.
Ronen의 솔루션은 다음과 같은 방법을 만드는 것입니다.FactoryBean
를 .FactoryBean
은 공장bean.spring 인터페이스에 수 .
현재 조롱하고 있는 콩 정의는 다음과 같습니다.
<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
<property name="type" value="com.package.Dao" />
</bean>
Spring 3.2부터는 이 문제가 발생하지 않게 되었습니다.스프링은 이제 일반적인 공장 방법의 결과 자동 배선을 지원합니다.이 블로그 투고의 「Generic Factory Methods」의 항을 참조해 주세요.http://spring.io/blog/2012/11/07/spring-framework-3-2-rc1-new-testing-features/
요점은 다음과 같습니다.
Spring 3.2에서는 공장 출하시 방법의 범용 반환 타입이 올바르게 추측되고 있으며, mock의 타입별 자동 배선은 예상대로 동작합니다.따라서 MockitoFactoryBean, EasyMockFactoryBean 또는 Springockito와 같은 사용자 지정 회피책은 더 이상 필요하지 않습니다.
즉, 즉시 사용할 수 있습니다.
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
스프링 >= 3.0을 사용하는 경우 스프링을 사용해 보십시오.@Configuration
@Configuration
@ImportResource("com/blah/blurk/rest-of-config.xml")
public class DaoTestConfiguration {
@Bean
public ApplicationService applicationService() {
return mock(ApplicationService.class);
}
}
@ImportResource를 사용하지 않을 경우 다른 방법으로도 사용할 수 있습니다.
<beans>
<!-- rest of your config -->
<!-- the container recognize this as a Configuration and adds it's beans
to the container -->
<bean class="com.package.DaoTestConfiguration"/>
</beans>
자세한 내용은 spring-framework-reference: Java 기반 컨테이너 구성을 참조하십시오.
아래 코드는 자동 배선과 연동됩니다.최단 버전은 아니지만 표준 스프링/모키토 항아리에서만 작동해야 하는 경우에 유용합니다.
<bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"> <bean class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="com.package.Dao" /> </bean> </property>
<property name="proxyInterfaces"> <value>com.package.Dao</value> </property>
</bean>
완벽한 해결책은 아닐지 모르지만 유닛 테스트에 스프링을 사용하지 않는 경향이 있습니다.일반적으로 단일 콩(테스트 대상 클래스)에 대한 종속성은 그다지 복잡하지 않기 때문에 테스트 코드에서 직접 주입을 수행합니다.
Mockito를 사용하여 다음을 할 수 있습니다.
<bean id="stateMachine" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.abcd.StateMachine"/>
</bean>
상기의 어프로치에 근거해 몇개의 예를 투고한다.
스프링 포함:
@ContextConfiguration(locations = { "classpath:context.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class TestServiceTest {
@InjectMocks
private TestService testService;
@Mock
private TestService2 testService2;
}
스프링 없음:
@RunWith(MockitoJUnitRunner.class)
public class TestServiceTest {
@InjectMocks
private TestService testService = new TestServiceImpl();
@Mock
private TestService2 testService2;
}
업데이트 - 새로운 답변은 https://stackoverflow.com/a/19454282/411229 에서 확인할 수 있습니다.이 답변은 3.2 이전 버전의 Spring에만 적용됩니다.
나는 이것에 대한 보다 확실한 해결책을 찾고 있었다.이 블로그 투고는 나의 모든 요구를 충족시키는 것 같고, 빈 신고서의 주문에 의존하지 않는다.모두 마티아스 시버슨 덕분입니다http://www.jayway.com/2011/11/30/spring-integration-tests-part-i-creating-mock-objects/
기본적으로 Factory Bean을 구현합니다.
package com.jayway.springmock;
import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;
/**
* A {@link FactoryBean} for creating mocked beans based on Mockito so that they
* can be {@link @Autowired} into Spring test configurations.
*
* @author Mattias Severson, Jayway
*
* @see FactoryBean
* @see org.mockito.Mockito
*/
public class MockitoFactoryBean<T> implements FactoryBean<T> {
private Class<T> classToBeMocked;
/**
* Creates a Mockito mock instance of the provided class.
* @param classToBeMocked The class to be mocked.
*/
public MockitoFactoryBean(Class<T> classToBeMocked) {
this.classToBeMocked = classToBeMocked;
}
@Override
public T getObject() throws Exception {
return Mockito.mock(classToBeMocked);
}
@Override
public Class<?> getObjectType() {
return classToBeMocked;
}
@Override
public boolean isSingleton() {
return true;
}
}
다음으로 스프링 구성을 다음과 같이 업데이트합니다.
<beans...>
<context:component-scan base-package="com.jayway.example"/>
<bean id="someDependencyMock" class="com.jayway.springmock.MockitoFactoryBean">
<constructor-arg name="classToBeMocked" value="com.jayway.example.SomeDependency" />
</bean>
</beans>
T의 도우미 .ImportBeanDefinitionRegistrar
어노멘트를 .@MockedBeans
조롱할 클래스를 지정할 수 있습니다.나는 이 접근방식이 모킹과 관련된 보일러 플레이트 코드 중 일부를 제거한 간결한 유닛 테스트 결과를 가져올 것이라고 믿는다.
샘플 유닛 테스트의 접근방식은 다음과 같습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class)
public class ExampleServiceIntegrationTest {
//our service under test, with mocked dependencies injected
@Autowired
ExampleService exampleService;
//we can autowire mocked beans if we need to used them in tests
@Autowired
DependencyBeanA dependencyBeanA;
@Test
public void testSomeMethod() {
...
exampleService.someMethod();
...
verify(dependencyBeanA, times(1)).someDependencyMethod();
}
/**
* Inner class configuration object for this test. Spring will read it thanks to
* @ContextConfiguration(loader=AnnotationConfigContextLoader.class) annotation on the test class.
*/
@Configuration
@Import(TestAppConfig.class) //TestAppConfig may contain some common integration testing configuration
@MockedBeans({DependencyBeanA.class, DependencyBeanB.class, AnotherDependency.class}) //Beans to be mocked
static class ContextConfiguration {
@Bean
public ExampleService exampleService() {
return new ExampleService(); //our service under test
}
}
}
주석(커스텀 주석의 간단한 클래스를 .이라는2개의 단순한 도우미 클래스를 정의해야 합니다.@MockedBeans
및)의 " " "ImportBeanDefinitionRegistrar
★★★★★★ 。@MockedBeans
의 정의에는 주석에 을 달아야 .@Import(CustomImportBeanDefinitionRegistrar.class)
및ImportBeanDefinitionRgistrar
「Configuration()」의 설정에 가 있습니다.registerBeanDefinitions
★★★★★★ 。
이 방법이 마음에 드신다면 제 블로그 포스트에서 구현 예를 찾을 수 있습니다.
Springockito의 개발 속도와 미해결 이슈 수를 보면 요즘 테스트 스위트 스택에 도입하는 것이 조금 걱정됩니다.마지막 발매가 봄 4 출시 전에 이루어졌다는 사실 때문에 "봄 4와 쉽게 통합할 수 있을까?"와 같은 의문이 든다.몰라, 안 먹어봐서.통합 테스트에서 스프링빈을 조롱해야 한다면 순수한 스프링 방식을 선호합니다.
밋밋한 스프링 기능만으로 봄콩을 모조할 수 있는 옵션이 있습니다. '어울리다'를 써야 요.@Primary
,@Profile
★★★★★★★★★★★★★★★★★」@ActiveProfiles
주석을 달아야 합니다.나는 그 주제에 대해 블로그에 글을 썼다.
저는 모크를 제공하는 Mock Factory를 만들기 위해 티보트와 비슷한 답변을 찾았습니다.다음 예를 사용하여 mock factory를 만들었습니다(narkisr에 대한 링크가 정지되어 있기 때문에).http://hg.randompage.org/java/src/407e78aa08a0/projects/bookmarking/backend/spring/src/test/java/org/randompage/bookmarking/backend/testUtils/MocksFactory.java
<bean id="someFacade" class="nl.package.test.MockFactory">
<property name="type" value="nl.package.someFacade"/>
</bean>
이것은 또한 스프링이 조롱당한 콩의 주사를 해결하기를 원하는 것을 막는데 도움이 된다.
<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
<property name="type" value="com.package.Dao" />
</bean>
이 ^는 XML 파일에서 처음 또는 초기에 선언되면 완벽하게 작동합니다.모키토 1.9.0/스프링 3.0.5
저는 Kresimir Nesek의 제안을 바탕으로 솔루션을 개발했습니다.코드를 좀 더 깔끔하고 모듈러형으로 만들기 위해 새로운 주석 @EnableMockedBean을 추가했습니다.
@EnableMockedBean
@SpringBootApplication
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=MockedBeanTest.class)
public class MockedBeanTest {
@MockedBean
private HelloWorldService helloWorldService;
@Autowired
private MiddleComponent middleComponent;
@Test
public void helloWorldIsCalledOnlyOnce() {
middleComponent.getHelloMessage();
// THEN HelloWorldService is called only once
verify(helloWorldService, times(1)).getHelloMessage();
}
}
저는 그것을 설명하는 글을 썼습니다.
저는 당신의 프로젝트를 Spring Boot 1.4로 이행할 것을 제안합니다.그런 다음 새 주석을 사용하여 새 주석을 위조할 수 있습니다.com.package.Dao
오늘 나는 모키토 콩 전에 a라고 선언한 봄 콘텍스트가 로딩되지 않았다는 것을 알았다.AFTER Mocks 이동 후 앱 컨텍스트가 성공적으로 로드되었습니다.주의하세요:)
참고로 모든 테스트는 고정장치를 느리게 초기화함으로써 올바르게 작동합니다. 예를 들어 다음과 같습니다.
<bean id="fixture"
class="it.tidalwave.northernwind.rca.embeddedserver.impl.DefaultEmbeddedServer"
lazy-init="true" /> <!-- To solve Mockito + Spring problems -->
<bean class="it.tidalwave.messagebus.aspect.spring.MessageBusAdapterFactory" />
<bean id="applicationMessageBus"
class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="it.tidalwave.messagebus.MessageBus" />
</bean>
<bean class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="javax.servlet.ServletContext" />
</bean>
Mattias가 여기서 설명하고 있는 근거는 (기사의 맨 아래) 회피책으로 콩이 선언된 순서를 변경하는 것이라고 생각합니다.- 느린 초기화는 마지막에 픽스쳐가 선언되는 것을 "일종의"이라고 하는 것입니다.
스프링 부트 2.2+를 사용하는 경우 @MockInBean을 대신 사용할 수 있습니다.@MockBean
봄의 문맥을 청결하게 유지합니다.
@SpringBootTest
public class MyServiceTest {
@MockInBean(MyService.class)
private ServiceToMock serviceToMock;
@Autowired
private MyService myService;
@Test
public void test() {
Mockito.when(serviceToMock.returnSomething()).thenReturn(new Object());
myService.doSomething();
}
}
면책사항:@MockBean/@SpringBean으로 인해 빌드 테스트 단계가 느려지는 것을 방지하기 위해 이 라이브러리를 만들었습니다(테스트에서 @MockBean을 사용하면 응용 프로그램콘텍스트가 강제로 새로고침되거나 @MockBean 문제가 발생하는 것을 참조하십시오).
언급URL : https://stackoverflow.com/questions/2457239/injecting-mockito-mocks-into-a-spring-bean
'programing' 카테고리의 다른 글
데이터 배열을 입력 매개 변수로 오라클 프로시저에 전달 (0) | 2023.04.04 |
---|---|
Eclipse의 스프링 부트 프로젝트에서 Maven과 함께 "메인 클래스를 찾을 수 없음" (0) | 2023.04.04 |
where 절에서 'case expression column' 사용 (0) | 2023.04.04 |
Woocommerce에서 '품절' 제품 숨기기 (0) | 2023.04.04 |
런타임에 개체의 클래스 이름 가져오기 (0) | 2023.04.04 |