Зависимости проводки в модульном тесте Spring без использования @RunWith - PullRequest
2 голосов
/ 09 февраля 2012

Я использую Spring 3 MVC / рамки безопасности.

Я создал класс Controller, который имеет ссылку на хранилище для загрузки данных. Класс аннотируется @Controller, класс репозитория аннотируется @Repository, а экземпляр репозитория - @Autowired.

Однако, когда я пытаюсь выполнить модульное тестирование, экземпляр с автосвязью выдает исключение нулевого указателя.

Теперь я понимаю, что, поскольку это автоматическое соединение, оно должно быть в пределах весеннего контекста, чтобы его можно было найти. Но я чувствую, что если я использую @RunsWith(), то это становится интеграционным тестом. Я действительно хотел бы разделить интеграционные тесты (используя @RunsWith) и модульный тест для этого метода. Любые идеи о том, как я могу обойти это исключение нулевого указателя? Разве можно было бы просто создать методы получения / установки на моем классе контроллера?:

Класс репозитория:

@Repository
public class Repository{
 ....
}

Класс контроллера:

@Controller
public class Controller{
@Autowired
private Repository repo;
....
public String showView(){
    repo.doSomething();
}

Тестовый класс:

public ControllerTest {
@Test
public shouldDoTestOfShowView(){
}
}

Ответы [ 3 ]

3 голосов
/ 09 февраля 2012

Лично я склонен использовать @ подход Саймона , а не выставлять сеттеры, хотя любой из этих подходов подходит. Однако добавление сеттеров только ради тестов немного раздражает.

Альтернативой является использование класса ReflectionTestUtils Spring * для непосредственного размещения зависимостей в поле с помощью отражения, устраняя необходимость в специальных конструкторах и установщиках, например,

public ControllerTest {
   @Test
   public shouldDoTestOfShowView() {
      Controller controller = new Controller();
      Repository repository = new Repository();

      ReflectionTestUtils.setField(controller, "repo", repository); 
   }
}

Является ли это «интеграционным тестом» или нет, это ваш вызов (не знаю).

2 голосов
/ 09 февраля 2012

Я всегда пишу 2 конструктора.Один без аргументов для Spring и защищенный со всеми зависимостями для модульного тестирования.

@Controller
public class Controller{
@Autowired
private Repository repo;

public Controller() {
    super();
}

protected Controller(Repositoy repo) {
    this();
    this.repo = repo;
}
0 голосов
/ 09 февраля 2012

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

Я написал утилитув прошлом он принимал два аргумента: целевой объект и объект, который вы устанавливаете для своей цели.

public static void set(Object target, Object setMeOnTarget) {
    //
}

То, что вы можете сделать здесь, - это самоанализ полей target в поисках Spring.поддерживаемые аннотации автопроводки (@Autowired, @Resource, @Inject, может быть, даже @Value) и посмотреть, можно ли присвоить этому полю setMeOnTarget (я использовал Class.isAssignableFrom(Class)).

Можетбыть немного хилым (Spring внезапно перестает поддерживать эти аннотации ... маловероятно ...), но это отлично сработало для меня.

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