Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Модульное тестирование в контексте запутанной пружины

Автор вопроса: BastlОтветов: 2

Учитывая, что устаревшее приложение имеет 1500 spring.xmls. Я хочу написать модульный тест для службы. Я глубоко в аду зависимости. Я должен принять приложение как есть, выхода нет.

Итак, мы используем spring-3.something и mockito-1.9, и мне нужен хороший способ протестировать сервис. В более новом коде активно используется аннотация @Autowired.

Косвенно сервис использует ~25 хелперов (фабричные методы и т.д.), которые я на самом деле хочу использовать в тесте, и ~25 объектов, которые мне не интересны для этого теста.

В настоящее время я пытаюсь настроить контекст так, как описано выше, но меня смущают эффекты @Mock, @InjectMocks, @Autowired.

Мой тест приведен ниже. Мне нужна помощь, чтобы настроить его правильно.

Вопросы:

  • каков фактический эффект @InjectMocks?
  • как я могу решить (технически), какие автосвязанные bean-компоненты действительно используются, а какие заменены макетами?
  • Я знаю, что злоупотребляю имитациями для получения подделок. Есть ли более простой способ получить подделки в однострочниках?
  • *Обратите внимание, что я хочу понять это, поскольку у меня есть множество таких сервисов... *

Вот мой образец:

@ContextConfiguration(locations = {
    "classpath:/some/path/MainTestConfig.spring.xml"
})
@RunWith(SpringJUnit4ClassRunner.class)
public class SampleTest {

    // ***            Uninteresting Dependencies to be mocked        *** //
    @Mock Mock1 mock1;
    @Mock Mock2 mock2;

    /** Service under test */
    @Autowired
    SomeService service;

    // ***            Tightly coupled helpers to be used              *** //
    @Autowired Helper1 helper1
    @Autowired Helper2 helpr2

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(SampleTest.class);
    }

    @Test
    public void testSample() {

        // prepare dummy context
        SomeContext context = new Context();

        // define expected result
        int expectedValue = 42;

        //execute method under test, record result
        Result actualResult = service.execute(context);

        //make assertions on result
        assertTrue(actualResult.getSomething()==expectedValue);
    }

}
  • Я не понимаю, почему у вас есть mock1 и mock2, которые кажутся неуместными в вашем тесте, поскольку они не имеют значения. Плюс помощники, похоже, не используются, проверено в тесте. Если все подключено к пружине, зачем вам это нужно. Я считаю, что вместо этого вы должны издеваться над тесно связанными помощниками и проверять взаимодействие. Кроме того, в конечном итоге вы можете написать этот тест как большой тест функциональности / функций, то есть не модульный тест или интеграционный тест, поэтому он будет помещен в какой-то другой пакет, чтобы показать разницу вашим коллегам. Brice 15.04.2013
  • Кстати, вы пробовали конфигурацию аннотаций, доступную весной 3? Это может быть полезно, если вам нужно внедрить только несколько зависимостей, и это может работать и для макетов (нет необходимости в springockito, если добавление другой зависимости от maven вызывает беспокойство). Brice 15.04.2013

springjunitmockitospringmockito

Ответы

Ответ 1 · рейтинг 4 · John B

Я хотел опубликовать это как отдельный ответ, так как это должно лучше ответить на ваш фактический вопрос относительно @Mock, @Autowired и @InjectMocks.

@Mock: это отмечает поле, которое должно быть создано как макет (с использованием mock(MyClass.class)) при вызове MockitoAnnotations.initMocks(this).

@Autowired: Помечает поле, которому Spring должен назначить bean-компонент, реализующий класс/интерфейс.

@InjectMocks: Отмечает поле, которое должно быть СОЗДАНО Mockito при вызове MockitoAnnoations.initMocks(this). Он создает экземпляр класса и вводит в этот экземпляр поля с аннотациями @Mock. (см. исправление к этому утверждению в комментариях).

Анализ:

@InjectMocks не совместим с контекстами Spring и @Autowired, потому что InjectMock создает новый экземпляр класса, который не использует экземпляр Spring.

Чтобы сделать то, что вы ищете, вам нужно использовать Springockito. (отложенное обновление) Springockito позволит вам вводить макеты в ваш контекст Spring и, таким образом, использовать эти макеты в качестве Autowired кандидатов. Это позволяет использовать Mocks и Spys. Использование ReplaceWithMock и Autowired в одном и том же поле в вашем тесте является общей практикой (как показано в примере на вики).

Ответ 2 · рейтинг 2 · John B

Первый вопрос: вам НУЖНО загружать контекст весны для этого теста? Обычно, когда у меня есть проекты Spring, у меня есть один UNIT-тест на класс, который НЕ загружает файл контекста. У меня будет другой тест CONTEXT для загрузки файла контекста и проверки правильности его загрузки. Если вы выполняете настоящее модульное тестирование, я бы посоветовал не загружать контекст. Если тестируемый класс использует @Autowired для назначения зависимостей (и поэтому не имеет сеттеров), используйте Spring ReflectionTestUtils для назначения этих полей.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы