Spring controller testing with dependencies failing












0















I have the following controller class:



@Controller
public class HelloController {

private final HelloService service;

public HelloController(HelloService service) {
this.service = service;
}

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}


As you can see, it accepts a dependency. This all runs fine in the server. However, when testing, it fails:



@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class WebLayerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/hello")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}


Below is the output of the log file in target/surefire-reports/



-------------------------------------------------------------------------------
Test set: biz.martyn.footy.WebLayerTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.278 s <<< FAILURE! - in biz.martyn.footy.WebLayerTest
shouldReturnDefaultMessage(biz.martyn.footy.WebLayerTest) Time elapsed: 0.005 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloController' defined in file [/home/martyn/eclipse-workspace/Footy/target/classes/biz/martyn/footy/controller/HelloController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}


I understand that @MockBean allows me to create a mock of the dependency, but in cases where I don't care to mock it? Here, I'm happy here for the real dependency instance to be used as normal. Or, is it because I'm only testing the web layer that it doesn't instantiate the controller as it would when running the full app?



UPDATE



I also tried @Autowired injection rather than constructor. My app works, so the dependency is brought into the controller, but the test fails. Below is the updated controller:



@Controller
public class HelloController {

@Autowired
private HelloService service;

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}









share|improve this question

























  • I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

    – John Camerin
    Nov 22 '18 at 18:51











  • Wouldn't that be MockMvc?

    – Martyn
    Nov 22 '18 at 19:18








  • 1





    Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

    – moilejter
    Nov 22 '18 at 19:21






  • 1





    No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

    – JB Nizet
    Nov 22 '18 at 20:05






  • 1





    @JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

    – moilejter
    Nov 22 '18 at 20:12
















0















I have the following controller class:



@Controller
public class HelloController {

private final HelloService service;

public HelloController(HelloService service) {
this.service = service;
}

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}


As you can see, it accepts a dependency. This all runs fine in the server. However, when testing, it fails:



@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class WebLayerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/hello")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}


Below is the output of the log file in target/surefire-reports/



-------------------------------------------------------------------------------
Test set: biz.martyn.footy.WebLayerTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.278 s <<< FAILURE! - in biz.martyn.footy.WebLayerTest
shouldReturnDefaultMessage(biz.martyn.footy.WebLayerTest) Time elapsed: 0.005 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloController' defined in file [/home/martyn/eclipse-workspace/Footy/target/classes/biz/martyn/footy/controller/HelloController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}


I understand that @MockBean allows me to create a mock of the dependency, but in cases where I don't care to mock it? Here, I'm happy here for the real dependency instance to be used as normal. Or, is it because I'm only testing the web layer that it doesn't instantiate the controller as it would when running the full app?



UPDATE



I also tried @Autowired injection rather than constructor. My app works, so the dependency is brought into the controller, but the test fails. Below is the updated controller:



@Controller
public class HelloController {

@Autowired
private HelloService service;

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}









share|improve this question

























  • I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

    – John Camerin
    Nov 22 '18 at 18:51











  • Wouldn't that be MockMvc?

    – Martyn
    Nov 22 '18 at 19:18








  • 1





    Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

    – moilejter
    Nov 22 '18 at 19:21






  • 1





    No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

    – JB Nizet
    Nov 22 '18 at 20:05






  • 1





    @JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

    – moilejter
    Nov 22 '18 at 20:12














0












0








0








I have the following controller class:



@Controller
public class HelloController {

private final HelloService service;

public HelloController(HelloService service) {
this.service = service;
}

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}


As you can see, it accepts a dependency. This all runs fine in the server. However, when testing, it fails:



@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class WebLayerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/hello")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}


Below is the output of the log file in target/surefire-reports/



-------------------------------------------------------------------------------
Test set: biz.martyn.footy.WebLayerTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.278 s <<< FAILURE! - in biz.martyn.footy.WebLayerTest
shouldReturnDefaultMessage(biz.martyn.footy.WebLayerTest) Time elapsed: 0.005 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloController' defined in file [/home/martyn/eclipse-workspace/Footy/target/classes/biz/martyn/footy/controller/HelloController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}


I understand that @MockBean allows me to create a mock of the dependency, but in cases where I don't care to mock it? Here, I'm happy here for the real dependency instance to be used as normal. Or, is it because I'm only testing the web layer that it doesn't instantiate the controller as it would when running the full app?



UPDATE



I also tried @Autowired injection rather than constructor. My app works, so the dependency is brought into the controller, but the test fails. Below is the updated controller:



@Controller
public class HelloController {

@Autowired
private HelloService service;

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}









share|improve this question
















I have the following controller class:



@Controller
public class HelloController {

private final HelloService service;

public HelloController(HelloService service) {
this.service = service;
}

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}


As you can see, it accepts a dependency. This all runs fine in the server. However, when testing, it fails:



@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class WebLayerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/hello")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}


Below is the output of the log file in target/surefire-reports/



-------------------------------------------------------------------------------
Test set: biz.martyn.footy.WebLayerTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.278 s <<< FAILURE! - in biz.martyn.footy.WebLayerTest
shouldReturnDefaultMessage(biz.martyn.footy.WebLayerTest) Time elapsed: 0.005 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloController' defined in file [/home/martyn/eclipse-workspace/Footy/target/classes/biz/martyn/footy/controller/HelloController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}


I understand that @MockBean allows me to create a mock of the dependency, but in cases where I don't care to mock it? Here, I'm happy here for the real dependency instance to be used as normal. Or, is it because I'm only testing the web layer that it doesn't instantiate the controller as it would when running the full app?



UPDATE



I also tried @Autowired injection rather than constructor. My app works, so the dependency is brought into the controller, but the test fails. Below is the updated controller:



@Controller
public class HelloController {

@Autowired
private HelloService service;

@RequestMapping("/hello")
public @ResponseBody String greeting() {
return service.greet();
}

}






java spring-mvc spring-test-mvc






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 19:52







Martyn

















asked Nov 22 '18 at 18:43









MartynMartyn

1,56571763




1,56571763













  • I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

    – John Camerin
    Nov 22 '18 at 18:51











  • Wouldn't that be MockMvc?

    – Martyn
    Nov 22 '18 at 19:18








  • 1





    Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

    – moilejter
    Nov 22 '18 at 19:21






  • 1





    No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

    – JB Nizet
    Nov 22 '18 at 20:05






  • 1





    @JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

    – moilejter
    Nov 22 '18 at 20:12



















  • I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

    – John Camerin
    Nov 22 '18 at 18:51











  • Wouldn't that be MockMvc?

    – Martyn
    Nov 22 '18 at 19:18








  • 1





    Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

    – moilejter
    Nov 22 '18 at 19:21






  • 1





    No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

    – JB Nizet
    Nov 22 '18 at 20:05






  • 1





    @JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

    – moilejter
    Nov 22 '18 at 20:12

















I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

– John Camerin
Nov 22 '18 at 18:51





I am assuming there is a Spring context somewhere for the application that wires HellowService into the HelloController. How is the Spring context loaded in test execution?

– John Camerin
Nov 22 '18 at 18:51













Wouldn't that be MockMvc?

– Martyn
Nov 22 '18 at 19:18







Wouldn't that be MockMvc?

– Martyn
Nov 22 '18 at 19:18






1




1





Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

– moilejter
Nov 22 '18 at 19:21





Maybe, if you had @Autowired the service to the controller, by adding that annotation to either the constructor or the property? I don't think SPring will autowire things for you without an explicit declaration, either in the code via an annotation, or via an XML context configuration file...

– moilejter
Nov 22 '18 at 19:21




1




1





No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

– JB Nizet
Nov 22 '18 at 20:05





No, Spring doesn't need any Autowired annotation if you only have one constructor. It autowires dependencies in that constructor by default. So your code is totally fine. If you want to test the whole thing, and not just the web layer with a mocked service layer, then don't use WebMvcTest. Use this: docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…

– JB Nizet
Nov 22 '18 at 20:05




1




1





@JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

– moilejter
Nov 22 '18 at 20:12





@JBNizet You're right :-) - looks like a feature that was added to Spring in 4.3: baeldung.com/constructor-injection-in-spring

– moilejter
Nov 22 '18 at 20:12












1 Answer
1






active

oldest

votes


















1














@WebMvcTest will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans, so you have to use @MockBean to satisfy the dependency.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436637%2fspring-controller-testing-with-dependencies-failing%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    @WebMvcTest will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans, so you have to use @MockBean to satisfy the dependency.






    share|improve this answer




























      1














      @WebMvcTest will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans, so you have to use @MockBean to satisfy the dependency.






      share|improve this answer


























        1












        1








        1







        @WebMvcTest will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans, so you have to use @MockBean to satisfy the dependency.






        share|improve this answer













        @WebMvcTest will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans, so you have to use @MockBean to satisfy the dependency.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 22 '18 at 20:35









        Danylo RosiichukDanylo Rosiichuk

        1494




        1494






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436637%2fspring-controller-testing-with-dependencies-failing%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            Refactoring coordinates for Minecraft Pi buildings written in Python