JUnit'te Çoklu RunWith İfadeleri


113

Birim testi yazıyorum ve kullanmak istiyorum JUnitParamsRunnerve MockitoJUnitRunnerbir test sınıfı için.

Maalesef aşağıdakiler çalışmıyor:

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

Mockito ve JUnitParams'ı tek bir test sınıfında kullanmanın bir yolu var mı?



2
Burada da güzel bir örnek var: blog.project13.pl/index.php/coding/1077/…
falsarella

Yanıtlar:


110

Bunu yapamazsınız çünkü spesifikasyona göre aynı notu aynı ek açıklamalı öğeye iki kez koyamazsınız.

Peki çözüm nedir? Çözüm, @RunWith()koşucuya sadece bir tane koymak ve diğerini başka bir şeyle değiştirmek. Sizin durumunuzda MockitoJUnitRunner, yaptığı şeyi programlı bir şekilde kaldıracak ve yapacaksınız.

Aslında yaptığı tek şey çalışıyor:

MockitoAnnotations.initMocks(test);

test senaryosunun başında. Dolayısıyla, en basit çözüm bu kodu setUp()yönteme koymaktır :

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

Emin değilim, ancak muhtemelen bayrak kullanarak bu yöntemin birden çok çağrılmasından kaçınmalısınız:

private boolean mockInitialized = false;
@Before
public void setUp() {
    if (!mockInitialized) {
        MockitoAnnotations.initMocks(this);
        mockInitialized = true;  
    }
}

Ancak daha iyisi, yeniden kullanılabilir çözüm JUnt'un kuralları ile uygulanabilir.

public class MockitoRule extends TestWatcher {
    private boolean mockInitialized = false;

    @Override
    protected void starting(Description d) {
        if (!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;  
        }
    }
}

Şimdi aşağıdaki satırı test sınıfınıza ekleyin:

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

ve bu test durumunu istediğiniz herhangi bir koşucu ile çalıştırabilirsiniz.


13
Çek mockInitializedyanlış. Her tetst için yeni bir taklit yapmak istiyorsun.
BetaRide

1
@BetaRide, ihtiyaçlarınıza bağlıdır. Bazen her seferinde sahte başlatmak istersiniz, bazen istemezsiniz.
AlexR

Sınıf dosyası başına bir kez oluşturmak istiyorsanız, Test dosyası başına bir kez ve yalnızca bir kez çağrılacak olan Before yerine BeforeClass'ı kullanabilirsiniz.
InfernalRapture

56

JUnit 4.7 ve Mockito 1.10.17'den itibaren bu işlevsellik yerleşiktir; bir org.mockito.junit.MockitoRulesınıf var. Basitçe içe aktarabilir ve satırı ekleyebilirsiniz

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

test sınıfınıza.


2
Mockito'nun eski sürümleri için (1.10.5'e düşmüş gibi görünüyor), şunları kullanmanız gerekir:@Rule public MockitoJUnitRule mockito = new MockitoJUnitRule(this);
Cliff Sun

MockitoAnnotations.initMocks(this)taklitler oluşturmak çok yavaştır. En etkili yol, @Runwith (MockitoJunitRunner.class)
ant2009

16

Bu çözüm, yalnızca bu sahte örnek için değil, olası her koşucu için işe yarar. Örneğin; Bahar için sadece koşucu sınıflarını değiştirin ve gerekli ek açıklamaları ekleyin.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

    @Test
    public void subRunner() throws Exception {
        JUnitCore.runClasses(TestMockitoJUnitRunner.class);
    }

    @RunWith(MockitoJUnitRunner.class)
    public static class TestMockitoJUnitRunner {
    }
}

DatabaseModelTestJUnit tarafından çalıştırılacaktır. TestMockitoJUnitRunner(mantığa göre) buna bağlıdır ve işletilecek içini bir ana ait @Testgörüşme sırasında, yöntemin JUnitCore.runClasses(TestMockitoJUnitRunner.class). Bu yöntem, static class TestMockitoJUnitRunneralt koşucu çalıştırılmadan önce ana koşucunun doğru şekilde başlatılmasını sağlar ve @RunWithbağımlı test sınıflarıyla birden çok iç içe ek açıklama etkili bir şekilde uygular .

Ayrıca https://bekce.github.io/junit-multiple-runwith-dependent-tests adresinde


3
Sonucu JUnitCore.runClasses()incelemeden arayarak , iç testten hataları maskeleme riskini alırsınız. assert(JUnitCore.runClasses(TestMockitoJUnitRunner.class).wasSuccessful());en azından hatayı size bildirecek
Robotnik


2

Benim durumumda, bahar fasulyesinde bir yöntemle alay etmeye çalışıyordum ve

MockitoAnnotations.initMocks(test);

çalışmıyor. Bunun yerine, aşağıdaki gibi xml dosyanızın içindeki mock yöntemini kullanarak oluşturulacak o çekirdeği tanımlamanız gerekir.

...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...

ve aşağıdaki gibi otomatik kablolanmış o fasulyeyi test sınıfınıza ekleyin.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
    ...
    @Autowired
    private ClassWantedToBeMocked classWantedToBeMocked;
    ...
    when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
    ...
}

0

bu bağlantıya göz atın https://bekce.github.io/junit-multiple-runwith-dependent-tests/ bu yaklaşımı kullanarak bir @RunWith (Parameterized.class) - dış koşucu - @RunWith (MockitoJUnitRunner.class) ile birleştirdim - iç koşucu. Eklemem gereken tek ince ayar, üye değişkenlerimi dış sınıf / koşucu statik hale getirerek iç / iç içe geçmiş koşucu / sınıf için erişilebilir kılmaktı. iyi şanslar ve keyfini çıkarın.


0

SWTBotJunit4ClassRunner ve org.junit.runners'ı aynı anda çalıştırmak istedim , parametrik testlerim var ve SWT testi başarısız olduğunda ekran görüntüsü almak istiyorum (ekran görüntüsü özelliği SWTBotJunit4ClassRunner tarafından sağlanıyor ). @ bekce'nin cevabı harika ve ilk önce o rotaya gitmek istedim ama argümanlardan geçmek ilginçti. Veya alt sınıfta parametreleştirilmiş olanı yapmak ve tam olarak hangi testlerin geçtiğini / başarısız olduğunu ve yalnızca son ekran görüntüsüne sahip olan bilgileri kaybetmek (ekran görüntüsü adları, adı testin kendisinden aldığı için). Yani her iki durumda da biraz dağınıktı.

Benim durumumda SWTBotJunit4ClassRunner yeterince basit, bu yüzden sınıfın kaynak kodunu klonladım, ona kendi adımı ParametrizedScreenshotRunner verdim ve orijinalin TestRunner'ı genişlettiği yerde , sınıfım Parameterized sınıfı genişletiyor, böylece özünde kendi runner'ımı kullanabilirim önceki ikisi yerine. Kaynatılmış kendi koşucum, üstüne ekran görüntüsü özelliğini uygularken Parametreli koşucunun üstüne uzanıyor, şimdi benim testim bu "hibrit" koşucuyu kullanıyor ve tüm testler beklendiği gibi hemen çalışıyor (testlerin içinde hiçbir şeyi değiştirmeye gerek yok).

Görünüşe göre böyle (kısaca listeden tüm yorumları kaldırdım):

package mySwtTests;

import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;

public class ParametrizedScreenshotRunner extends TestRu Parameterized {

    public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
        super(klass);
    }

    public void run(RunNotifier notifier) {
        RunListener failureSpy = new ScreenshotCaptureListener();
        notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
        notifier.addListener(failureSpy);
        try {
            super.run(notifier);
        } finally {
            notifier.removeListener(failureSpy);
        }
    }
}

-15

Ayrıca şunu da deneyebilirsiniz:

@RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
  // some tests
}

@RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
  // some tests
}

2
Bu işe yaramayacak, sadece alt sınıf ek açıklaması işlenecek.
PaulNUK

çalışmıyor - sadece MockitoJUnitRunner ek açıklaması dikkate alınacak
Przemek Bielicki
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.