Кілька заяв 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.