Как получить доступ к объекту Spring @Service из теста JUnit

#java #spring #junit

#java #spring #junit

Вопрос:

Ситуация: у меня есть класс реализации сервиса с аннотацией @Service с доступом к файлу свойств.

 @Service("myService")
public class MySystemServiceImpl implements SystemService{

      @Resource
      private Properties appProperties;

}
  

Объект свойств настраивается через конфигурационный файл. applicationContext.xml

 <util:properties id="appProperties" location="classpath:application.properties"/>
  

Я хочу протестировать некоторые методы этой реализации.

Вопрос: Как получить доступ к MySystemServiceImpl-объекту из тестового класса таким образом, чтобы свойства appProperties были инициализированы должным образом?

 public class MySystemServiceImplTest {

    //HOW TO INITIALIZE PROPERLY THROUGH SPRING? 
    MySystemServiceImpl testSubject;

    @Test
    public void methodToTest(){
        Assert.assertNotNull(testSubject.methodToTest());
    }     

}
  

Я не могу просто создать новый MySystemServiceImpl — методы, которые используют appProperties, вызывают исключение NullPointerException. И я не могу напрямую вводить свойства в объект — нет подходящего метода установки.

Просто укажите правильные шаги здесь (спасибо @NimChimpsky за ответ):

  1. Я скопировал application.properties в раздел test /resources.

  2. Я скопировал applicationContext.xml в стадии тестирования / реж. ресурсов. В контексте приложения я добавляю новый компонент (определение свойств приложения уже здесь):

     <bean id="testSubject" class="com.package.MySystemServiceImpl">
      
  3. Я модифицировал тестовый класс таким образом:

     @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"/applicationContext.xml"})
    public class MySystemServiceImplTest {
    
       @Autowired
       MySystemServiceImpl testSubject;
    
    }
      
  4. И это делает трюк — теперь в моем тестовом классе доступен полностью функциональный объект

Ответ №1:

В качестве альтернативы, чтобы выполнить интеграционный тест, я делаю это.

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext-test.xml"})
@Transactional
public class MyTest {

    @Resource(name="myService")
    public IMyService myService;
  

Затем используйте сервис, как обычно. Добавьте контекст приложения в свой каталог test / resources

Ответ №2:

Просто используйте его конструктор :

 MySystemServiceImpl testSubject = new MySystemServiceImpl();
  

Это модульный тест. Модульный тест проверяет класс изолированно от других классов и инфраструктуры.

Если ваш класс имеет зависимости от других интерфейсов, смоделируйте эти интерфейсы и создайте объект с этими макетами в качестве аргумента. В этом весь смысл внедрения зависимостей: возможность вводить другие, фиктивные реализации внутри объекта, чтобы легко протестировать этот объект.

Редактировать:

Вы должны предоставить сеттер для вашего объекта properties, чтобы иметь возможность вводить нужные свойства для каждого из модульных тестов. Введенные свойства могут содержать номинальные значения, экстремальные значения или неправильные значения в зависимости от того, что вы хотите протестировать. Внедрение полей практично, но плохо сочетается с модульным тестированием. При модульном тестировании предпочтительнее использовать инъекцию конструктора или установщика, поскольку основная цель внедрения зависимостей заключается именно в том, чтобы иметь возможность вводить фиктивные или конкретные зависимости в модульные тесты.

Комментарии:

1. К сожалению, у меня нет возможности изменять класс. Вот почему я должен придерживаться Spring injection. Во всем остальном я согласен с вашей точкой зрения

2. Есть ли какой-либо недостаток в том, чтобы не вводить?