@RunWith (MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks (this)


118

Yeni bir jUnit4 testi yazarken, @RunWith (MockitoJUnitRunner.class) veya MockitoAnnotations.initMocks (this) kullanıp kullanmamayı merak ediyorum .

Yeni bir test oluşturdum ve sihirbaz Runner ile otomatik olarak bir test oluşturdu. MockitoJUnitRunner için Javadocs şunları belirtir:

JUnit 4.4 ve üstü ile uyumlu olan bu çalıştırıcı aşağıdaki davranışı ekler:

Mock ile açıklanmış taklitleri başlatır, böylece MockitoAnnotations.initMocks (Object) öğesinin açık kullanımı gerekli değildir. Modeller, her test yönteminden önce başlatılır. her test yönteminden sonra çerçeve kullanımını doğrular.

Runner'ı kullanmanın geçmişte kullandığım initMocks () yöntemine göre herhangi bir avantajı olup olmadığı bana açık değil .

Herhangi bir düşünce veya bağlantı takdir edilecektir!

Yanıtlar:


147

MockitoJUnitRunnersize çerçeve kullanımının otomatik olarak doğrulanmasının yanı sıra otomatik initMocks().

Çerçeve kullanımının otomatik olarak doğrulanması aslında sahip olmaya değer. Bu hatalardan birini yaparsanız size daha iyi raporlama sağlar.

  • Statik çağrı whenyöntemini, ancak eşleşen Stubbing tamamlamayan thenReturn, thenThrowya then. (Aşağıdaki kodda Hata 1)

  • verifySahte arama yaparsınız , ancak doğrulamaya çalıştığınız yöntem çağrısını sağlamayı unutursunuz. (Aşağıdaki kodda Hata 2)

  • Sen buna whensonra yöntemini doReturn, doThrowya doAnswerve bir taklidini geçmesi, ancak saplama çalıştığınız yöntem sağlamak unutur. (Aşağıdaki kodda Hata 3)

Çerçeve kullanımı doğrulamasına sahip değilseniz, bu hatalar bir Mockito yöntemine yapılan aşağıdaki çağrıya kadar rapor edilmez. Bu olabilir

  • aynı test yönteminde (aşağıdaki hata 1 gibi),
  • sonraki test yönteminde (aşağıdaki hata 2 gibi),
  • bir sonraki test sınıfında.

Çalıştırdığınız son testte meydana gelirlerse (aşağıdaki 3. hata gibi), hiç rapor edilmeyeceklerdir.

İşte bu tür hataların her birinin nasıl görünebileceği aşağıda açıklanmıştır. Burada, JUnit'in bu testleri burada listelendikleri sırayla çalıştırdığını varsayalım.

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called.
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen.
    when(myMock.method1());

    doSomeTestingStuff();

    // ERROR 1 is reported on the following line, even though it's not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call to verify.  But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error.
    doReturn("Hello").when(myMock).method1();


    // ERROR 3
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call is being stubbed.  But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen.

    doReturn("World").when(myMock);

    doSomeTestingStuff(); 

    //  ERROR 3 is never reported, because there are no more Mockito calls. 
}

Beş yıldan daha uzun bir süre önce bu cevabı ilk yazdığımda, yazdım

Bu yüzden MockitoJUnitRunnermümkün olan her yerde kullanılmasını tavsiye ederim . Ancak, Tomasz Nurkiewicz'in doğru bir şekilde işaret ettiği gibi, Spring gibi başka bir JUnit koşucusuna ihtiyacınız varsa onu kullanamazsınız.

Önerim şimdi değişti. Mockito ekibi, bu cevabı ilk yazdığımdan beri yeni bir özellik ekledi. Bu bir JUnit kuralıdır ve .NET Framework ile tamamen aynı işlevi yerine getirir MockitoJUnitRunner. Ama daha iyi çünkü diğer koşucuların kullanımını engellemez.

Dahil etmek

@Rule 
public MockitoRule rule = MockitoJUnit.rule();

test sınıfınızda. Bu, taklitleri başlatır ve çerçeve doğrulamasını otomatikleştirir; tıpkı yaptığı gibi MockitoJUnitRunner. Ama şimdi, SpringJUnit4ClassRunnerya da başka bir JUnitRunner'ı da kullanabilirsiniz . Mockito 2.1.0'dan itibaren, tam olarak ne tür sorunların rapor edileceğini kontrol eden ek seçenekler vardır.


kesinlikle aynı olduklarını söyleyemem. bir test durumunda, junit runner kurulumu benim için başarısız oluyor ve initMocks kurulumunu yapmadığım sürece taklitlerimi doğru şekilde enjekte etmiyor
dtc

6.8.8 + mockito 1.10.19 testini kullanıyoruz ve açıkçası MockitoJUnitRunner'ı kullanamıyoruz, ancak doğrulama çerçevesi hala çalışıyor! Ve tam olarak @David Wallace gibi çalışır. Biri açıklayabilir mi? Bunun nedeni hala @ Before * geri aramalarına ve MockitoAnnotations.initMocks'a (bu) sahip olmamız mı?
yuranos

@ yuranos87 Yeni bir soru olarak sormanız gereken bir şeye benziyor. Bunu yaparken kodunuzu eklemeyi unutmayın - eğer kodu göstermezseniz "bu kod neden XYZ yapıyor" diye sormak biraz anlamsız.
Dawood ibn Kareem

1
TestRunner çözümünü kullanmak, @Rule'dan çok daha iyi performans gösteriyor
Kural

1
@alexandroid En iyi önerim, kullanarak kendi cevabınızı yazmanızdır @ExtendWith. Bu gerçekten bildiğim bir şey değil. Stack Overflow ile ilgili harika olan şey, böyle bir soruda birden fazla doğru yanıt verebilmenizdir.
Dawood ibn Kareem

23

Runner'ı kullanmak, biraz kodlamadan tasarruf etmenizi sağlar ( @Beforeyönteme gerek yoktur ). Öte yandan bir koşucu kullanmak bazen mümkün değildir, yani zaten bir tane kullanıyorsanız SpringJUnit4ClassRunner.

Bu kadar. Bu sadece bir tercih meselesi.


2
İnitMocks () satırı dışında, @Before yöntemi diğer kurulumlar için hala gerekli olacaktır, değil mi?
OceanBlue

2
@OceanBlue: Elbette @Beforeyönteminiz initMocks()koşucuya geçtikten sonra saklamanız gerekenden başka bir şey içeriyorsa .
Tomasz Nurkiewicz

David Wallace'ın çerçevenin geçerliliği hakkındaki cevabı sorumu tamamen cevapladı, bu yüzden bunu kabul ettim, ancak +1, bu koşucunun Bahar gibi başka bir koşucu ile kullanılamayacağına işaret ettiği için. Teşekkürler!
OceanBlue

1
Spring Boot kullanıyorum ve bunun SpringJUnit4ClassRunnerbenim için otomatik olarak alayları başlattığını söyleyebilirim . Yine de basit Bahar hakkında bir şey bilmiyorum.
gustavohenke
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.