Кілька заяв RunWith в jUnit


113

Я пишу одиничний тест і хочу використовувати JUnitParamsRunnerі MockitoJUnitRunnerдля одного тестового класу.

На жаль, наступне не працює:

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

Чи є спосіб використання обох, Mockito та JUnitParams в одному тестовому класі?



2
Тут також є приємний приклад: blog.project13.pl/index.php/coding/1077/…
falsarella

Відповіді:


110

Ви не можете цього зробити, тому що відповідно до специфікації ви не можете двічі ставити одну й ту саму примітку на один і той же примітка.

Отже, яке рішення? Рішення полягає в тому, щоб поставити лише одного @RunWith()з бігуном, без якого ви не можете стояти, а іншого замінити чимось іншим. У вашому випадку я думаю, ви видалите MockitoJUnitRunnerта зробите програмно те, що це робить.

Насправді єдине, що він робить:

MockitoAnnotations.initMocks(test);

на початку тестового випадку. Отже, найпростішим рішенням є введення цього коду в setUp()метод:

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

Я не впевнений, але, мабуть, вам слід уникати багаторазового виклику цього методу, використовуючи прапор:

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

Однак краще, багаторазове рішення може бути реалізоване з правилами JUnt.

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

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

Тепер просто додайте наступний рядок до свого тестового класу:

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

і ви можете запустити цей тестовий випадок з будь-яким бажаним бігуном.


12
Чек на mockInitializedпомилковий. Ви хочете мати свіжий макет для кожного тесту.
BetaRide

1
@BetaRide, це залежить від ваших потреб. Іноді хочеться щоразу ініціалізувати макет, іноді ні.
AlexR

Якщо ви хочете налаштувати один раз на файл класу, ви можете використовувати BeforeClass замість «Перед», який буде викликати один раз і лише один раз на тестовий файл.
InfernalRapture

56

Станом на JUnit 4.7 та Mockito 1.10.17 ця функціональність вбудована; є org.mockito.junit.MockitoRuleклас. Ви можете просто імпортувати його та додати рядок

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

до вашого тестового класу.


2
Для старих версій Mockito (здається, до 1.10.5) ви повинні використовувати:@Rule public MockitoJUnitRule mockito = new MockitoJUnitRule(this);
Кліфф

MockitoAnnotations.initMocks(this)дуже повільно створює макети. Найефективніший спосіб - використовувати @Runwith (MockitoJunitRunner.class)
ant2009,

16

Це рішення працює для кожного можливого бігуна, а не лише для цього макетного прикладу. Наприклад; Для весни просто поміняйте класи бігунів та додайте необхідні примітки.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

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

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

DatabaseModelTestбуде керувати JUnit. TestMockitoJUnitRunnerвід цього залежить (за логікою), і він запускатиметься всередині основного @Testметодом під час виклику JUnitCore.runClasses(TestMockitoJUnitRunner.class). Цей метод забезпечує правильний static class TestMockitoJUnitRunnerзапуск основного бігуна перед запуском суб-бігуна, ефективно реалізуючи кілька вкладених @RunWithанотацій із залежними класами тестування.

Також на https://bekce.github.io/junit-multiple-runwith-dependent-tests


3
Зателефонувавши, JUnitCore.runClasses()не перевіряючи результат, ви ризикуєте замаскувати помилки з внутрішнього тесту. assert(JUnitCore.runClasses(TestMockitoJUnitRunner.class).wasSuccessful());принаймні повідомить вам про помилку
Robotnik


2

У моєму випадку я намагався знущатися з якихось методів весняним бобом і

MockitoAnnotations.initMocks(test);

не працює. Натомість ви повинні визначити, що було створено за допомогою методу mock у вашому XML-файлі, як описано нижче.

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

і додайте цей боб із автоматичним провідником всередині вашого тестового класу, як описано нижче.

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

0

перевірте це посилання https://bekce.github.io/junit-multiple-runwith-dependent-tests/, використовуючи цей підхід, я поєднав @RunWith (Parameterized.class) - зовнішній бігун - з @RunWith (MockitoJUnitRunner.class) - внутрішній бігун. Єдине налаштування, яке мені довелося додати, - це зробити змінні мого члена в зовнішньому класі / бігуні статичними, щоб зробити їх доступними для внутрішнього / вкладеного бігуна / класу. гук удачі і насолоджуйся.


0

Я хотів запустити SWTBotJunit4ClassRunner та org.junit.runners.Parameterized в той же час, у мене є параметричні тести, і я хочу зробити знімки екрана, коли тест SWT завершився (функцію скріншоту надає SWTBotJunit4ClassRunner ). Відповідь @ bekce чудова і спочатку хотіла пройти цей маршрут, але це було або химерно, проходячи аргументи. Або робити параметризований у підкласі та втрачати інформацію про те, які точні тести пройшли / провалились та мають лише останній скріншот (як назви скріншотів отримують назву від самого тесту). Так що в будь-якому випадку було трохи безладно.

У моєму випадку SWTBotJunit4ClassRunner досить простий, тому я клонував вихідний код класу, дав йому власне ім’я ParametrizedScreenshotRunner, і де оригінал розширював TestRunner , мій клас розширює клас Параметризований, тому по суті я можу використовувати власний бігун замість попередніх двох. Опущений мій власний бігун поширюється на параметризований бігун, реалізуючи функцію скріншоту поверх нього, тепер мій тест використовує цей "гібридний" бігун, і всі тести працюють, як очікувалося, відразу (не потрібно нічого змінювати всередині тестів).

Ось як це виглядає (заради стислості я видалив усі коментарі зі списку):

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

Ви також можете спробувати це:

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

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

2
Це не спрацює, оброблятиметься лише анотація підкласу.
PaulNUK

не працює - враховуватиметься лише анотація MockitoJUnitRunner
Przemek Bielicki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.