6

I have multiple controllers and my understanding is that by specifying one controller in @WebMvcTest that other controllers wouldn't be loaded into context. From the docs

controllers - Specifies the controllers to test. May be left blank if all @Controller beans should be added to the application context.

My first Controller

@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);
    }

}

My other controller

@Controller
public class MyOtherController {

    @Autowired
    private MyOtherService myOtherService;

    etc...
}

My Test for my Controller

@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());
    }
}

But when I run this test, it fails trying to load the bean MyOtherService from MyOtherContoller when loading the context.

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)}

I thought specifying the controller to test in the WebMvcTest annotation would limit it to the only loading that contoller. But its trying to load the other controller and because its beans aren't mocked it fails.

What am I missing or is my understanding incorrect? I think I should only have to mock beans for the Controller under test. I've also tried an excludeFilter to specifically exclude the package for the other Controller but that didn't change the error.

1
  • what does your application class look like? Commented Sep 28, 2017 at 11:39

2 Answers 2

10

Please make sure the Application.class your test picks up, doesn't contain @ComponentScan annotation. For example, this is your package structure

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

The Application.java under test should look similar to this example,

@SpringBootApplication
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @Indra, I think that's my issue alright. I have a \@ComponentScan as I need to explicitly filter to exclude some Components in an included jar. I'm looking now to change that so I have a separate Application class when running WebMvcTests
Thanks, you made my day. I was getting a different error (Spring tried to instantiate a bean buried down in the context, that shouldn't be instantiated in the test) and your advice worked for me as well.
I'm having the same issue, but unfortunately, this solution doesn't work for me. The @SpringBootApplication annotation comes with @ComponentScan if I remove @ComponentScan every test started giving 404
@IvanVilanculo Without seeing how your project is structured, it would be difficult for me to comment
0

my.package.other.myOtherMapper (probably Mybatis Mapper file) is missing or not clearly initialized.

As of my understanding, myOtherService implementation class has Mapper file which is not mapped properly.

You may have to map them first. You can post the Mapper xml content if possible.

  <context:component-scan base-package="org.example">       
    <context:exclude-filter type="custom" expression="abc.xyz.MyOtherController"/>
  </context:component-scan>

7 Comments

Yes myOtherMapper is not intiialiased but its trying to instantiate it because its trying to load MyOtherController into context. If that controller was excluded from context, which I think it should be, then myOtherService wouldn't be looked for and hence myOtherMapper wouldn't be looked for.
I could get around it by adding @MockBean in the test for MyOtherService but I shouldn't have to mock every service to test a Controller that only uses one service.
thanks but I already tried an exclude filter to ignore the package for the other controller, didn't make a difference
stackoverflow.com/questions/13034515/… you can exclude a specific class as per this answer. You might have issues on other area
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.