Enjekte Mockito bir bahar fasulye alay ediyor


284

JUnit ile birim testi için bir Mockito sahte nesne bir Bahar (3+) fasulye içine enjekte etmek istiyorum. Fasulye bağımlılıklarım şu anda @Autowiredözel üye alanlarına ek açıklama kullanılarak enjekte ediliyor .

Ben kullanmayı düşündüm ReflectionTestUtils.setFieldama enjekte etmek istiyorum fasulye örneği aslında bir proxy ve bu nedenle hedef sınıfın özel üye alanlarını bildirmez. Bağımlılığa genel bir ayarlayıcı oluşturmak istemiyorum çünkü daha sonra tamamen test amacıyla arayüzümü değiştireceğim.

Bahar topluluğu tarafından verilen bazı tavsiyelere uydum , ancak alay oluşturulmaz ve otomatik kablolama başarısız olur:

<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.package.Dao" />
</bean>

Şu anda karşılaştığım hata aşağıdaki gibidir:

...
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-argDeğeri geçersiz bir şeye ayarlarsam , uygulama bağlamını başlatırken hiçbir hata oluşmaz.


4
Bu minicik yaratık bir göz atın lütfen: bitbucket.org/kubek2k/springockito/wiki/Home
kubek2k

Bu çok temiz bir yaklaşım - hoşuma gitti!
teabot

2
Beni Springockito ek açıklamalarında tuttun.
yihtserns


2
Bahar 4'ü * kullananlar için, Ocak 2015 itibariyle bu, en son bahar mockito sürümü ile çalışmıyor gibi görünüyor ve proje etkin değil gibi görünüyor.
Murali

Yanıtlar:


130

En iyi yol:

<bean id="dao" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="com.package.Dao" /> 
</bean> 

Güncelleme
Bağlam dosyasında, bu alay, bildirime bağlı olarak herhangi bir otomatik kablolu alandan önce listelenmelidir.


Bir hata alıyorum: "'mockito' adıyla fasulye oluşturulurken hata oluştu: fasulye tanımı soyut"
tttppp

4
@ amra: bahar bu durumda döndürülen nesnenin türünü
çıkarmaz

7
Bu cevabın neden bu kadar çok oy verildiğini bilmiyorum, sonuçta ortaya çıkan fasulye yanlış tipte olduğu için otomatik olarak bağlanamıyor.
azerole

4
Bağlam dosyasında ilk olarak listelenmişse otomatik kablolu olabilir (buna bağlı herhangi bir otomatik kablolu alan bildirilmeden önce)
Ryan Walls

3
İlkbahar 3.2 itibariyle, fasulyelerin sırası artık önemli değil. Bu blog yazısında "Jenerik Fabrika Yöntemleri" başlıklı bölüme bakın: spring.io/blog/2012/11/07/…
Ryan Walls

110
@InjectMocks
private MyTestObject testObject;

@Mock
private MyDependentObject mockedObject;

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

Bu, alay konusu nesneleri test sınıfına enjekte eder. Bu durumda mockedObject öğesini testObject içine enjekte eder. Bu yukarıda belirtilmişti ama işte kod.


1
Belirli bir yöntemi nasıl saplayabilirim mockedObject?
Jim Holden

@Teinacher (mockedObject.execute) .thenReturn (objToReturn); Bunu bir önceki yöntemde veya test yönteminizin içine koyabilirsiniz.
chaostheory

40
FYI: MyTestObject'te kısmi AutoWiring ve kısmi alay etmek istiyorsam bu yaklaşım çalışmaz.
raksja

9
Bunun neden daha yüksek oy verilmediğini bilmiyorum. XML içeren başka yanıtlar görürsem fırlatacağım.
MarkOfHall

3
Mockito.spy(...)Bunun mockedObjectyerine neden bunu kullanmıyorsunuz ? Ve sonra when(mockedObject.execute).thenReturn(objToReturn)veya kullanın doReturn(objToReturn).when(mockedObject).execute(). İkincisi, gerçek bir yöntemi çağırmayın. Ayrıca Mockito.doCallRealMethod()belgeleri de kontrol edebilirsiniz
Tomasz Przybylski

63

Spring Java Config ve Mockito kullanarak çok basit bir çözüm var:

@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;
    }
}

4
Nedense bu yaklaşım ile bahar gerçek fasulye (sahte yerine) yine de yaratmaya çalışır ve boğucu ... Ne yanlış yapıyorum?
Daniel Gruszczyk

1
Aynı sorunum var
Korobko Alex

3
Bahar değil, mockito bir sınıfla alay ediyorsanız gerçek bir fasulyeyi somutlaştırmaya çalışır. Testlerde alay edilmesi gereken herhangi bir fasulyeniz varsa, bunlar bir arayüzün uygulamaları olmalı ve bu arayüz üzerinden enjekte edilmelidir. Daha sonra arabirimi (sınıf yerine) alay ederseniz, mockito bu sınıfı başlatmaya çalışmaz.
Daniel Gruszczyk

7
Amaç ne? Açıklamalı alanları ve yapıcıyı neden eklemelisiniz initMocks? Neden sadece return Mockito.mock(BeanA.class)içinde getBeanA? Bu şekilde daha basit ve daha az kod var. Neyi kaçırıyorum?
Oleg

1
@Oleg, büyük olasılıkla bir cevap olarak yayınlamanız gereken kendi çözümünüz var gibi görünüyor, böylece topluluk buna oy verebilir.
Dawood ibn Kareem

48

Verilen:

@Service
public class MyService {
    @Autowired
    private MyDAO myDAO;

    // etc
}

Test edilen sınıfa otomatik kablolama ile yüklenebilir, Mockito ile bağımlılığı alay edebilir ve daha sonra mock'i ​​test edilen sınıfa enjekte etmek için Spring's ReflectionTestUtils kullanabilirsiniz.

@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
}

Bahar 4.3.1'den önce, bu yöntemin bir proxy'nin arkasındaki hizmetlerle ( örneğin açıklamalı @Transactionalveya Cacheableörneğin) çalışmadığını lütfen unutmayın . Bu SPR-14050 ile giderildi .

Önceki sürümlerde, çözüm burada açıklandığı gibi proxy'nin paketini açmaktır: İşlemsel ek açıklama, hizmetlerin alay edilmesini önler ( ReflectionTestUtils.setFieldvarsayılan olarak şu anda budur)


Double @RunWith (SpringJUnit4ClassRunner.class) ve test sınıfı (aynı koşucu) için farklı ek açıklamalar kullanıyorum ama bu yaklaşım benim için çalışıyor, teşekkürler.
user1317422

1
"İlkbahar 4.3.1'den önce bu yöntemin bir proxy'nin arkasındaki hizmetlerle (örneğin @Transactional veya Cacheable ile açıklamalı) çalışmadığından çok ilham aldım. Bu, SPR-14050 ile düzeltildi". Bu konuyla tam olarak karşılaştım ve bu kelimeleri görene kadar hiçbir ipucu alamadım. ÇOK TEŞEKKÜRLER!
snowfox

1
Bu çözüm, tüm uygulama bağlamını bağladığınızda ve test amacıyla, bağlamınızdaki rastgele bir fasülye bir sahte enjekte etmek istediğinde işler. Bu cevabı, bir Modül testindeki diğer modüllere REST çağrılarını önlemek için bir sahte müşteri fasulyesini taklit etmek için kullandım. Sadece Bahar Uygulama Yapılandırması tarafından oluşturulan bir fasulye değil, test etmek üzere olduğunuz bir fasulye alay enjekte ederken InjectMock ek açıklama var.
Andreas Lundgren

1
Neredeyse bir gün @MockBean içeriğini sıfırlamadan çalışmayı denemek etrafında kabartmak ve sonra bu gem rastlamak. Tam olarak ihtiyacım olan şey, şerefe.
Matt R

Çalışır, ancak değiştirilen alanın önbellekleme nedeniyle sıfırlanamayacağına ve bazı ilgisiz testlerin kırılabileceğine dikkat edin. Örneğin testimde şifre kodlayıcıyı sahte bir kodla değiştirdim ve yetkilendirme hataları nedeniyle birkaç test daha kırıldı.
alextsil

36

Spring Boot 1.4 kullanıyorsanız, bunu yapmanın harika bir yolu var. Sadece @SpringBootTestsınıfınızda ve @MockBeansahada yeni bir marka kullanın ve Spring Boot bu tip bir alay yaratacak ve onu içeriğe enjekte edecektir (orijinal olanı enjekte etmek yerine):

@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");
    }

}

Öte yandan, Spring Boot kullanmıyorsanız veya önceki bir sürümü kullanıyorsanız, biraz daha fazla iş yapmanız gerekir:

@ConfigurationAlaylarınızı Bahar bağlamına enjekte eden bir fasulye oluşturun :

@Configuration
@Profile("useMocks")
public class MockConfigurer {

    @Bean
    @Primary
    public MyBean myBeanSpy() {
        return mock(MyBean.class);
    }
}

@PrimaryEk açıklama kullanarak , bir niteleyici belirtilmezse, bu çekirdeğin önceliğe sahip olduğunu söyler.

@Profile("useMocks")Hangi sınıfların sahte kullanacağını ve hangilerinin gerçek fasulyeyi kullanacağını kontrol etmek için sınıfa açıklama eklediğinizden emin olun .

Son olarak, testinizde userMocksprofili etkinleştirin :

@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() {
        ....
    }
}

Alaycı değil gerçek fasulyeyi kullanmak istemiyorsanız useMocksprofili etkinleştirmeyin :

@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() {
        ....
    }
}

5
Bu cevap en başa gitmelidir - Bahar önyüklemede @MockBean desteği bahar önyükleme olmadan da kullanılabilir. Sadece ünite testlerinde kullanabilirsiniz, böylece tüm yay uygulamalarında çalışır!
bedrin

2
Ek açıklama @Profile ayrı konfigürasyon sınıfını yaratarak önlemek için, fasulye tanım yöntemine de ayarlayabilirsiniz
Marcin

Mükemmel cevap! Eski okul web.xmlve AnnotationConfigWebApplicationContext kurulumumla çalışmasını sağlamak için birkaç değişiklik yaptım . Kullanmak zorunda @WebAppConfigurationyerine @WebIntegrationTestve @ContextHierarchybirlikte @ContextConfigurationyerine @SpringApplicationConfiguration.
UTF_or_Death

Benim @Primarydurumum için açıklama eklemek zorunda kaldım , çünkü içinde @PostConstructalay etmek istediğimde başarısız bir çağrı vardı , ama @PostConstruct'fasulyesi benim alaydan önce oluşturuldu, bu yüzden sahte kullanmadım (ekleyene kadar @Primary).
cehennem

19

Yana 1.8.3 mockito vardır@InjectMocks - bu son derece yararlıdır. Benim JUnit testler şunlardır ve hazırlamayı özel üye ile açıklamalı edildiğinde tüm enjekte edildiği, sınıfın tüm bağımlılıkları test edilmekte tatmin nesneleri .@RunWithMockitoJUnitRunner@Mock@InjectMocks

Ben sadece şimdi entegrasyon testleri için.@RunWithSpringJUnit4Runner

List<T>İlkbaharla aynı şekilde enjekte edilemediğini not edeceğim . Yalnızca Mock nesnelerini karşılayan Listve Mock nesnelerinin listesini enjekte etmeyecek bir Mock nesnesi arar . Benim için geçici çözüm, @Spyel ile başlatılmış bir listeye karşı a kullanmak ve el ile .ck birim (ler) i birim sınama için bu listeye ekleyin. Belki de kasıtlıydı, çünkü kesinlikle birlikte alay edilene çok dikkat etmem gerekti.


Evet bu en iyi yol. Springockito benim durumumda herhangi bir sebepten dolayı alayları enjekte etmiyor.
chaostheory

13

Güncelleme: Artık bu soruna daha iyi, daha temiz çözümler var. Lütfen önce diğer cevapları düşünün.

Sonunda blogunda ronen tarafından bir cevap buldum. Sahip olduğum sorun Mockito.mock(Class c)bir dönüş türü bildirme yöntemi nedeniyle Object. Sonuç olarak Spring, fasulye türünü fabrika yöntemi dönüş türünden çıkaramaz.

Ronen'in çözümü , alaylarıFactoryBean döndüren bir uygulama oluşturmaktır . FactoryBeanArayüz Bahar fabrika fasulye yarattığı nesnelerin türünü sorgulamak için izin verir.

Alaycı fasulye tanımım şimdi şöyle görünüyor:

<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
    <property name="type" value="com.package.Dao" />
</bean>


Bunu anlamıyorum, fabrika metodunun dönüş tipi Object var ... Ama amra'nın çözümü genel bir dönüş tipine sahip, böylece Spring bunu tanımalı ... Ama amra'nın çözümü benim için çalışmıyor
lisak

Ne bu çözüm, bahar fabrikadan döndürülen fasulye türünü çıkarmazBuna bu nedenle [com.package.Dao] türü eşleşen fasulye yok ...
lisak


Bu bağlantı aslında hala çalışıyor: javadevelopmentforthemasses.blogspot.com/2008/07/… Tarayıcınızda bağlantı yeniden yönlendirmeyi devre dışı bırakın ve yeni blogunda 404'e bakmak yerine zorla göreceksiniz.
approxiblue

12

İlkbahar 3.2 itibariyle, bu artık bir sorun olmaktan çıkmıştır. Spring artık genel fabrika yöntemlerinin sonuçlarının Otomatik Kablolamasını destekliyor. Bu blog yazısında "Genel Fabrika Yöntemleri" başlıklı kısma bakın: http://spring.io/blog/2012/11/07/spring-framework-3-2-rc1-new-testing-features/ .

Kilit nokta:

Bahar 3.2'de, fabrika yöntemleri için genel dönüş türleri artık doğru bir şekilde çıkarılmıştır ve alaylar için türe göre otomatik kablolama beklendiği gibi çalışmalıdır. Sonuç olarak, MockitoFactoryBean, EasyMockFactoryBean veya Springockito gibi özel çözümlere artık gerek yoktur.

Bu, kutunun dışında çalışması gerektiği anlamına gelir:

<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.package.Dao" />
</bean>

9

Aşağıdaki kod otomatik kablolama ile çalışır - en kısa sürüm değildir, ancak sadece standart yay / mockito kavanozlarıyla çalışması gerektiğinde yararlıdır.

<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> 

Benim için çalıştı. Burada açıklandığı gibi doğrulamak için testimdeki proxy'yi açmam
Holgzn

9

Eğer kullanıyorsanız yayı> = 3.0 , Yaylar kullanmayı deneyin @Configurationuygulama bağlamında kısmı tanımlamak için ek açıklama

@Configuration
@ImportResource("com/blah/blurk/rest-of-config.xml")
public class DaoTestConfiguration {

    @Bean
    public ApplicationService applicationService() {
        return mock(ApplicationService.class);
    }

}

@ImportResource kullanmak istemiyorsanız, bunun tersi de yapılabilir:

<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>

Daha fazla bilgi için, yay-çerçeve-başvurusuna bakın: Java tabanlı kapsayıcı yapılandırması


Güzel bir. Bunu test ettiğim test gerçek test durumunda @Autowired olduğunda kullandım.
enkor

8

Belki de mükemmel bir çözüm değil, ama birim testleri için DI yapmak için yay kullanmama eğilimindeyim. tek bir fasulye (test altındaki sınıf) için bağımlılıklar genellikle aşırı karmaşık değildir, bu yüzden sadece doğrudan test kodunda enjeksiyon yapmak.


3
Yaklaşımını anlıyorum. Ancak, kendimi bu durumda kolayca buna izin vermeyen büyük bir eski kod tabanı üzerinde buluyorum - henüz.
Mart'ta

1
Ben çok Bahar yönleri / AOP (örneğin, bahar güvenlik kurallarını test ederken) bağlı kod test etmek gerektiğinde Mockito / Bahar açılan çok yararlı buldum. Her ne kadar bu tür testlerin bir entegrasyon testi olması gerektiğini iddia etmek mükemmel bir şekilde gerekçelendirilmiş olsa da.
Lars Tackmann

@Lars - kabul edildi - uğraştığım testler için de aynı şey söylenebilir.
Mart'ta

7

Mockito kullanarak aşağıdakileri yapabilirim:

<bean id="stateMachine" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.abcd.StateMachine"/>
</bean>

1
@Alexander cevabınız için teşekkürler. Sorabilir miyim: doğru bağlanıyor mu? Eğer öyleyse, hangi Spring / Mockito versiyonlarını kullanıyorsunuz?
teabot

6

Yukarıdaki yaklaşımlara dayanan birkaç örnek gönderme

Bahar ile:

@ContextConfiguration(locations = { "classpath:context.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class TestServiceTest {
    @InjectMocks
    private TestService testService;
    @Mock
    private TestService2 testService2;
}

Yaysız:

@RunWith(MockitoJUnitRunner.class)
public class TestServiceTest {
    @InjectMocks
    private TestService testService = new TestServiceImpl();
    @Mock
    private TestService2 testService2;
}

2

Güncelleme - burada yeni yanıt: https://stackoverflow.com/a/19454282/411229 . Bu cevap sadece 3.2'den önceki Bahar versiyonları için geçerlidir.

Bir süre daha kesin bir çözüm aradım. Bu blog gönderisi tüm ihtiyaçlarımı karşılıyor ve fasulye beyanları siparişine dayanmıyor. Mattias Severson'a tüm kredi. http://www.jayway.com/2011/11/30/spring-integration-tests-part-i-creating-mock-objects/

Temel olarak, bir FactoryBean uygulayın

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;
    }
}

Ardından, yay yapılandırmanızı aşağıdakilerle güncelleyin:

<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>

2

Springockito'nun gelişme hızına ve açık konuların sayısına bakmak bugünlerde test paketi biraz endişe ediyorum. Son sürümün Bahar 4 sürümünden önce yapıldığı gerçeği "Bahar 4 ile kolayca entegre etmek mümkün mü?" Bilmiyorum, çünkü denemedim. Entegrasyon testinde Spring bean ile alay etmem gerekirse saf Spring yaklaşımını tercih ederim.

Bahar çekirdeğini sadece düz Bahar özellikleri ile takma seçeneği vardır. Sen kullanmak gerekir @Primary, @Profileve @ActiveProfilesbunun için ek açıklamalar. Konuyla ilgili bir blog yazısı yazdım.


1

Ben alay sağlayan bir MockFactory oluşturmak için teabot benzer bir cevap buldum. Sahte fabrikayı oluşturmak için aşağıdaki örneği kullandım (narkisr'e bağlantı öldüğünden): http://hg.randompage.org/java/src/407e78aa08a0/projects/bookmarking/backend/spring/src/test/java/ org / randompage / imleme / arka uç / testUtils / MocksFactory.java

<bean id="someFacade" class="nl.package.test.MockFactory">
    <property name="type" value="nl.package.someFacade"/>
</bean>

Bu aynı zamanda Spring'in alaycı fasulyeden enjeksiyonları çözmek istemesini önlemeye yardımcı olur.


1
<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
    <property name="type" value="com.package.Dao" />
</bean>

XML dosyasında ilk / erken bildirildiyse bu ^ mükemmel çalışır. Mockito 1.9.0 / Bahar 3.0.5


1

Markus T tarafından yanıtta kullanılan yaklaşımın ve ImportBeanDefinitionRegistrarözel bir ek açıklama arayan basit bir yardımcı uygulamanın bir kombinasyonunu kullanıyorum (@MockedBeans hangi sınıfların alay edileceğini belirleyebileceği ) . Bu yaklaşımın, alay konusu ile ilgili bazı kaynak kodunun kaldırıldığı kısa bir birim testiyle sonuçlandığına inanıyorum.

Örnek bir birim testi bu yaklaşımla şöyle görünür:

@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
        }
    }
}

Bunu yapmak için iki basit yardımcı sınıf tanımlamanız gerekir - özel ek açıklama ( @MockedBeans) ve özel ImportBeanDefinitionRegistraruygulama. @MockedBeansaçıklama tanım ihtiyaçları ile açıklamalı edilecek @Import(CustomImportBeanDefinitionRegistrar.class)ve ImportBeanDefinitionRgistrar's içinde yapılandırmaya alay fasulye tanımları eklemesi gerekir registerBeanDefinitionsyöntemle.

Eğer yaklaşım seviyorsanız örnek bulabilirsiniz uygulamaları benim üzerinde blogpost .


1

Kresimir Nesek'in önerisine dayanan bir çözüm geliştirdim. Kodu biraz daha temiz ve modüler hale getirmek için yeni bir ek açıklama @EnableMockedBean ekledim .

@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();
    }

}

Bunu açıklayan bir yazı yazdım .


1

Projenizi Spring Boot 1.4'e taşımanızı öneririm. Bundan sonra, @MockBeantaklit etmek için yeni ek açıklama kullanabilirsiniz .com.package.Dao


0

Bugün Mockito fasulyesinden önce ilan ettiğim bir bahar bağlamının yüklenemediğini öğrendim. Alaycılardan SONRA taşındıktan sonra uygulama içeriği başarıyla yüklendi. Kendine iyi bak :)


1
Birşey eksik. 8-) Alay ettikten sonra ne taşıdın?
Hans-Peter Störr

0

Kayıt için, tüm testlerim fikstürün tembel olarak başlatılmasını sağlayarak doğru şekilde çalışır, örneğin:

<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>

Gerekçesinin Mattias'ın burada ( yazının altında) açıkladığı bir neden olduğunu, bir geçici çözümün fasulyelerin bildirildiği sırayı değiştirdiğidir - tembel başlatma, fikstürün sonunda bildirilen "çeşit" tir.


-1

Controller Injection kullanıyorsanız, yerel değişkenlerinizin "final" OLMADIĞINDAN emin olun

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.