Как исключить другие @Controller из моего контекста при тестировании с использованием Spring Boot @WebMvcTest

2

У меня несколько контроллеров, и я понимаю, что, указав один контроллер в @WebMvcTest, другие контроллеры не будут загружены в контекст. Из docs

Контроллеры

- Указывает контроллеры для проверки. Может быть оставлено пустым, если все @Controller beans должны быть добавлены в контекст приложения.

Мой первый контроллер

@Controller
public class MyController {

    @Autowired
    private MyService myService;

    private final Logger logger = Logger.getLogger(this.getClass());

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public @ResponseBody ResponseEntity<String> index() {
        try {
            myService.get();
            return new ResponseEntity<String>(HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e);
            e.printStackTrace();
        }
        return new ResponseEntity<String>("REQUEST FAILED", HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

Мой другой контроллер

@Controller
public class MyOtherController {

    @Autowired
    private MyOtherService myOtherService;

    etc...
}

Мой тест для моего контроллера

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = { MyController.class }, secure = false)
@ActiveProfiles({ "test" })
public class MyControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    MyService myService;

    @Test
    public void testBaseReq() throws Exception {
        Testing dummyData = new Testing();
        dummyData.setData("testing");
        when(myService.get(anyInt())).thenReturn(dummyData);

        this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk());
    }
}

Но когда я запускаю этот тест, он не пытается загрузить bean MyOtherService из MyOtherContoller при загрузке контекста.

2017-09-28 11:50:11.687 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'myOtherController'
2017-09-28 11:50:11.687 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating instance of bean 'myOtherController'
2017-09-28 11:50:11.687 DEBUG 16552 --- [           main] o.s.b.f.annotation.InjectionMetadata     : Registered injected element on class [my.package.other.myOtherController]: AutowiredFieldElement for private my.package.other.myOtherService my.package.other.myOtherController.myOtherService
2017-09-28 11:50:11.687 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Eagerly caching bean 'myOtherController' to allow for resolving potential circular references
2017-09-28 11:50:11.687 DEBUG 16552 --- [           main] o.s.b.f.annotation.InjectionMetadata     : Processing injected element of bean 'myOtherController': AutowiredFieldElement for private my.package.other.myOtherService my.package.other.myOtherController.myOtherService
2017-09-28 11:50:11.688 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'myOtherService'
2017-09-28 11:50:11.688 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating instance of bean 'myOtherService'
2017-09-28 11:50:11.689 DEBUG 16552 --- [           main] o.s.b.f.annotation.InjectionMetadata     : Registered injected element on class [my.package.other.myOtherService]: AutowiredFieldElement for private my.package.other.myOtherMapper my.package.other.myOtherService.myOtherMapper
2017-09-28 11:50:11.689 DEBUG 16552 --- [           main] o.s.b.f.annotation.InjectionMetadata     : Registered injected element on class [my.package.other.myOtherService]: AutowiredFieldElement for private ie.aib.services.coredemo.FinancialsRegionService my.package.other.myOtherService.financialsRegionService
2017-09-28 11:50:11.689 DEBUG 16552 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Eagerly caching bean 'myOtherService' to allow for resolving potential circular references
2017-09-28 11:50:11.689 DEBUG 16552 --- [           main] o.s.b.f.annotation.InjectionMetadata     : Processing injected element of bean 'myOtherService': AutowiredFieldElement for private my.package.other.myOtherMapper my.package.other.myOtherService.myOtherMapper
2017-09-28 11:50:11.690  WARN 16552 --- [           main] o.s.w.c.s.GenericWebApplicationContext   : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myOtherController': Unsatisfied dependency expressed through field 'myOtherService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myOtherService': Unsatisfied dependency expressed through field 'myOtherMapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'my.package.other.myOtherMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Я думал, что спецификация контроллера для тестирования в аннотации WebMvcTest ограничит его единственной загрузкой этого контоллера. Но его попытка загрузить другой контроллер и потому что его beans не издеваются, он терпит неудачу.

Что мне не хватает, или мое понимание неверно? Я думаю, мне нужно было только высмеять beans для тестируемого Контролера. Я также попробовал excludeFilter, чтобы специально исключить пакет для другого контроллера, но это не изменило ошибку.

  • 0
    как выглядит класс вашего приложения?
Теги:
spring-boot
unit-testing
spring
junit

2 ответа

3
Лучший ответ

Пожалуйста, убедитесь, что ваш тест Application.class, не содержит аннотации @ComponentScan. Например, это ваша структура пакета

abc-project
  +--pom.xml
  +--src
    +-- main
      +-- com
        +-- abc
          +-- Application.java
          +-- controller
            +-- MyController.java
    +-- test
      +-- com
        +-- abc
          +-- Application.java
          +-- controller
            +-- MyControllerTest.java

Application.java в тесте должен выглядеть примерно так,

@SpringBootApplication
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}
  • 0
    Спасибо @Indra, я думаю, что это моя проблема в порядке. У меня есть \ @ComponentScan, так как мне нужно явно фильтровать, чтобы исключить некоторые Компоненты во включенном фляге. Я смотрю сейчас, чтобы изменить это, поэтому у меня есть отдельный класс приложения при запуске WebMvcTests
  • 0
    Спасибо, ты сделал мой день. Я получал другую ошибку (Spring пытался создать экземпляр bean-компонента, скрытого в контексте, который не должен создаваться в тесте), и ваш совет тоже работал для меня.
0

my.package.other.myOtherMapper(возможно, файл Mybatis Mapper) отсутствует или явно не инициализирован.

По моему мнению, класс реализации myOtherService имеет файл Mapper, который неправильно отображается.

Возможно, вам придется сначала сопоставить их. Вы можете разместить содержимое xml Mapper, если это возможно.

  <context:component-scan base-package="org.example">       
    <context:exclude-filter type="custom" expression="abc.xyz.MyOtherController"/>
  </context:component-scan>
  • 0
    Да, myOtherMapper не инициализируется, но пытается его создать, потому что пытается загрузить MyOtherController в контекст. Если этот контроллер был исключен из контекста, что, я думаю, должно быть, тогда myOtherService не будет найден и, следовательно, myOtherMapper не будет найден.
  • 0
    Я мог бы обойти это, добавив @MockBean в тест для MyOtherService, но мне не нужно было насмехаться над каждым сервисом, чтобы протестировать контроллер, который использует только один сервис.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню