@Mock, @MockBean ve Mockito.mock () arasındaki fark


148

Testler oluştururken ve bağımlılıkları alay ederken, bu üç yaklaşım arasındaki fark nedir?

  1. @MockBean:

    @MockBean
    MyService myservice;
  2. @Mock:

    @Mock
    MyService myservice;
  3. Mockito.mock ()

    MyService myservice = Mockito.mock(MyService.class);

Yanıtlar:


200

Düz Mockito kitaplığı

import org.mockito.Mock;
...
@Mock
MyService myservice;

ve

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

Mockito kütüphanesinden gelir ve işlevsel olarak eşdeğerdir.
Bir sınıf veya arayüzle alay etmeye ve üzerindeki davranışları kaydetmeye ve doğrulamaya izin verirler.

Ek açıklamayı kullanma şekli daha kısadır, bu nedenle tercih edilir ve sıklıkla tercih edilir.


Test yürütmeleri sırasında Mockito açıklamalarını etkinleştirmek için MockitoAnnotations.initMocks(this)statik yöntemin çağrılması gerektiğini unutmayın.
Testler arasında yan etkiden kaçınmak için, her test uygulamasından önce yapılması tavsiye edilir:

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

Mockito açıklamalarını etkinleştirmenin başka bir yolu , bu görevi yapan ve diğer yararlı şeyleri @RunWithbelirterek test sınıfına açıklama eklemektir MockitoJUnitRunner:

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}

Mockito kitaplığını saran Spring Boot kitaplığı

Bu gerçekten bir Spring Boot sınıfıdır :

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

Sınıf spring-boot-testkitaplığa dahildir .

Bir İlkbaharda Mockito taklitleri eklemeye izin verir ApplicationContext.
İlan sınıf ile uyumlu bir fasulye, bağlamda varsa, yerini taklidinin bunu.
Durum böyle değilse, taklidi bağlama fasulye olarak ekler .

Javadoc referansı:

Spring ApplicationContext'e taklitler eklemek için kullanılabilen ek açıklama.

...

Bağlamda tanımlanan aynı türden herhangi bir mevcut tek fasulye, sahte ile değiştirilecekse, mevcut bir fasulye tanımlanmamışsa yeni bir tane eklenecektir.


Klasik / sade Mockito ne zaman @MockBeanve Spring Boot'tan ne zaman kullanılır ?

Birim testleri, bir bileşeni diğer bileşenlerden ayrı olarak test etmek için tasarlanmıştır ve birim testlerinin de bir gereksinimi vardır: bu testler geliştirici makinelerde her gün onlarca kez yürütülebileceğinden, yürütme süresi açısından olabildiğince hızlı olmak.

Sonuç olarak, işte basit bir kılavuz:

Spring Boot konteynerinden herhangi bir bağımlılık gerektirmeyen bir test yazarken, klasik / sade Mockito izlenecek yoldur: hızlıdır ve test edilen bileşenin izolasyonunu destekler.
Testinizin Spring Boot konteynırına güvenmesi gerekiyorsa ve ayrıca konteyner çekirdeklerinden birini eklemek veya taklit etmek istiyorsanız: @MockBeanSpring Boot'tan yol budur.


Spring Boot'un tipik kullanımı @MockBean

Açıklamalı bir test sınıfı yazarken @WebMvcTest(web test dilimi).

Spring Boot belgeleri bunu çok iyi özetliyor:

Genellikle @WebMvcTesttek bir denetleyiciyle sınırlı olacak ve @MockBeangerekli ortak çalışanlar için sahte uygulamalar sağlamak üzere birlikte kullanılacaktır.

İşte bir örnek :

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}

4
@MockBean kullanmak, çekirdeğin bir kopyasını oluşturacak ve bunu ApplicationContext'e enjekte edecek mi? Yoksa alay edilen fasulyenin tüm yöntemleri boş mu olacak? Tüm yöntemler boşsa, bunları @Mock kullanarak yapabildiğim gibi saplayabilir miyim?
Doug

6
Açıklandığı gibi @MockBean, Spring konfigürasyonunuzda aynı türü bildiren bir fasulye zaten tanımlanmışsa, uygulama bağlamında kullanılması fasulyenin yerini alacaktır. Ve enjeksiyon, bildirdiğiniz sınıfta gerçekleştirilir. @MockBean.DI mekanizmaları şu şekilde çalışır: DI bağlamında bir nesne kaydedersiniz ve ardından Spring bağlamında başvurulan nesneyi belirli bir sınıfa enjekte edebilirsiniz. DI bağlamında bir nesne enjekte etmezsiniz.
davidxxx

13

Sonunda açıklaması kolay. Ek açıklamaların javadoc'larına sadece bakarsanız, farklılıkları göreceksiniz:

@Mock: ( org.mockito.Mock)

Bir alanı sahte olarak işaretleyin.

  • Steno taklit oluşturmaya izin verir.
  • Tekrarlayan sahte oluşturma kodunu en aza indirir.
  • Test sınıfını daha okunaklı hale getirir.
  • Alan adı sahteyi tanımlamak için kullanıldığından doğrulama hatasını daha kolay okunur hale getirir.

@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean)

Spring ApplicationContext'e taklitler eklemek için kullanılabilen ek açıklama. Sınıf düzeyinde açıklama olarak veya @Configurationsınıflardaki alanlarda veya @RunWithSpringRunner olan test sınıflarında kullanılabilir.

Modeller, türe veya fasulye adına göre kaydedilebilir. Bağlamda tanımlanan aynı türden herhangi bir mevcut tek fasulye, mevcut bir fasulye tanımlanmadıysa yeni bir tane eklenecektir.

Bir @MockBeansahada kullanıldığında ve uygulama bağlamında kaydedildiğinde, taklit alana da enjekte edilecektir.

Mockito.mock ()

Bu sadece bir @Mock.


5
Unutmayalım ki @Mock, MockitoRunner veya initMocks'un manuel olarak çağrılmasını gerektirir.
Florian Schaetz

4
Arasındaki tek fark var mı @MockBeanve @Mockbir içine alay enjekte edeceğini Spring ApplicationContextve diğer iradeyi değil?
Doug

3
@Doug İyi özetlediniz ama MockBean'ın Spring Boot'un bir parçası olduğunu hatırlamanız gerekiyor
comiventor
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.