Beberapa Pernyataan RunWith di jUnit

113

Saya menulis tes unit dan ingin menggunakan JUnitParamsRunnerdan MockitoJUnitRunneruntuk satu kelas tes.

Sayangnya, berikut ini tidak berhasil:

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

Apakah ada cara untuk menggunakan keduanya, Mockito dan JUnitParams dalam satu kelas pengujian?

Hans-Helge
sumber
2
Ada contoh yang bagus di sini juga: blog.project13.pl/index.php/coding/1077/…
falsarella

Jawaban:

110

Anda tidak dapat melakukan ini karena menurut spesifikasi Anda tidak dapat meletakkan anotasi yang sama dua kali pada elemen beranotasi yang sama.

Lalu apa solusinya? Solusinya adalah dengan menempatkan hanya satu @RunWith()dengan pelari Anda tidak dapat berdiri tanpanya dan mengganti yang lain dengan yang lain. Dalam kasus Anda, saya kira Anda akan menghapus MockitoJUnitRunnerdan melakukan programatik apa yang dilakukannya.

Faktanya, satu-satunya hal yang dilakukannya adalah:

MockitoAnnotations.initMocks(test);

di awal kasus uji. Jadi, solusi paling sederhana adalah memasukkan kode ini ke dalam setUp()metode:

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

Saya tidak yakin, tetapi mungkin Anda harus menghindari beberapa panggilan dari metode ini menggunakan flag:

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

Namun lebih baik, solusi yang dapat digunakan kembali dapat diimplementasikan dengan aturan JUnt.

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

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

Sekarang tambahkan saja baris berikut ke kelas pengujian Anda:

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

dan Anda dapat menjalankan kasus uji ini dengan pelari mana pun yang Anda inginkan.

AlexR
sumber
12
Ceknya mockInitializedsalah. Anda ingin memiliki tiruan baru untuk setiap tetst.
BetaRide
1
@BetaRide, itu tergantung pada kebutuhan Anda. Terkadang Anda ingin menginisialisasi tiruan setiap saat, terkadang tidak.
AlexR
Jika Anda ingin menyiapkan satu kali per file kelas, Anda dapat menggunakan BeforeClass daripada Before, yang akan dipanggil sekali dan hanya sekali per file pengujian.
InfernalRapture
56

Mulai JUnit 4.7 dan Mockito 1.10.17, fungsionalitas ini sudah ada di dalamnya; ada org.mockito.junit.MockitoRulekelas. Anda cukup mengimpornya dan menambahkan garis

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

ke kelas pengujian Anda.

Erica Kane
sumber
2
Untuk versi Mockito yang lebih lama (tampaknya turun ke 1.10.5), Anda harus menggunakan:@Rule public MockitoJUnitRule mockito = new MockitoJUnitRule(this);
Cliff Sun
MockitoAnnotations.initMocks(this)sangat lambat untuk membuat tiruan. Cara paling efisien adalah dengan menggunakan @Runwith (MockitoJunitRunner.class)
ant2009
16

Solusi ini berfungsi untuk setiap pelari yang mungkin, bukan hanya contoh mockito ini. Sebagai contoh; untuk Spring, cukup ubah kelas pelari dan tambahkan anotasi yang diperlukan.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

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

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

DatabaseModelTestakan dijalankan oleh JUnit. TestMockitoJUnitRunnertergantung padanya (dengan logika) dan itu akan dijalankan di dalam main dalam sebuah @Testmetode, selama panggilan JUnitCore.runClasses(TestMockitoJUnitRunner.class). Metode ini memastikan runner utama dimulai dengan benar sebelum static class TestMockitoJUnitRunnersub-runner berjalan, yang secara efektif mengimplementasikan beberapa @RunWithanotasi bertingkat dengan class pengujian dependen.

Juga di https://bekce.github.io/junit-multiple-runwith-dependent-tests

bekce
sumber
3
Dengan memanggil JUnitCore.runClasses()tanpa memeriksa hasilnya, Anda berisiko menutupi kesalahan dari pengujian bagian dalam. assert(JUnitCore.runClasses(TestMockitoJUnitRunner.class).wasSuccessful());setidaknya akan melaporkan kesalahan tersebut kepada Anda
Robotnik
2

Dalam kasus saya, saya mencoba mengolok-olok beberapa metode dalam kacang musim semi dan

MockitoAnnotations.initMocks(test);

tidak bekerja. Sebagai gantinya Anda harus mendefinisikan kacang itu untuk dibangun menggunakan metode tiruan di dalam file xml Anda seperti berikut.

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

dan tambahkan kacang itu dengan autowired di dalam kelas pengujian Anda seperti berikut.

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

lihat tautan ini https://bekce.github.io/junit-multiple-runwith-dependent-tests/ menggunakan pendekatan ini saya menggabungkan @RunWith (Parameterized.class) - pelari luar - dengan @RunWith (MockitoJUnitRunner.class) - pelari batin. Satu-satunya perubahan yang harus saya tambahkan adalah membuat variabel anggota saya di kelas luar / pelari statis untuk membuatnya dapat diakses untuk pelari / kelas dalam / bersarang. gook luck dan nikmatilah.

Legna
sumber
0

Saya ingin menjalankan SWTBotJunit4ClassRunner dan org.junit.runners.Parameterized pada saat yang sama, saya memiliki tes parametrik dan saya ingin screenshot ketika tes SWT gagal (fitur screenshot disediakan oleh SWTBotJunit4ClassRunner ). Jawaban @ bekce bagus dan pertama kali ingin pergi ke rute itu tetapi itu aneh saat melewati argumen. Atau melakukan parametrized di subclass dan kehilangan informasi tes apa yang lulus / gagal dan hanya memiliki screenshot terakhir (karena nama screenshot mendapatkan nama dari pengujian itu sendiri). Jadi bagaimanapun juga itu agak berantakan.

Dalam kasus saya, SWTBotJunit4ClassRunner cukup sederhana, jadi saya mengkloning kode sumber kelas, memberinya nama saya sendiri ParametrizedScreenshotRunner dan di mana aslinya memperpanjang TestRunner , kelas saya memperluas kelas Parameterized sehingga pada dasarnya saya dapat menggunakan pelari saya sendiri bukan dua sebelumnya. Mendidih pelari saya sendiri meluas di atas pelari Parameterized saat menerapkan fitur screenshot di atasnya, sekarang pengujian saya menggunakan pelari "hybrid" dan semua tes bekerja seperti yang diharapkan langsung (tidak perlu mengubah apa pun di dalam tes).

Seperti inilah tampilannya (agar singkatnya saya menghapus semua komentar dari daftar):

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);
        }
    }
}
muni764
sumber
-15

Anda juga dapat mencoba ini:

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

@RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
  // some tests
}
Valentin Uveges
sumber
2
Ini tidak akan berfungsi, hanya anotasi subkelas yang akan diproses.
PaulNUK
tidak berfungsi - hanya penjelasan MockitoJUnitRunner yang akan diperhitungkan
Przemek Bielicki