MockBean stubbing ineffective












0














I have a configuration class with a few MockBeans replacing actual beans in context for tests.



@Configuration
public class MyTestConfig {
@MockBean
private MyService myService;
}


I use those mocks in my tests:



@Import({ MyTestConfig .class })
public class MyTest {
@Autowired
private MyService myService;

@Test
public void aTest() {
...
}
}


First the idea was to add the stubbing in this MyTestConfig configuration class, so that the mock is pre-made for all tests, so I did it in a @PostConstruct method, and it worked just fine - the mock in test did return the expected value:



@PostConstruct
public void init() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


It turned out though, that constructing a pre-made mock suitable for all test can be tricky, so we decided to move the stubbing to tests.



@Test
public void aTest() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


And this doesn't work - the stubbed method returns null. We want to leave MockBeans in the configuration class, but stub them in tests, so any advice on why the stubbing is ineffective?



Spring Boot 2.0.5, Mockito 2.22.0










share|improve this question


















  • 1




    I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
    – M. Deinum
    Nov 23 '18 at 8:08










  • @M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
    – snw
    Nov 23 '18 at 8:38








  • 1




    If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
    – M. Deinum
    Nov 23 '18 at 8:40










  • @M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
    – snw
    Nov 23 '18 at 9:05
















0














I have a configuration class with a few MockBeans replacing actual beans in context for tests.



@Configuration
public class MyTestConfig {
@MockBean
private MyService myService;
}


I use those mocks in my tests:



@Import({ MyTestConfig .class })
public class MyTest {
@Autowired
private MyService myService;

@Test
public void aTest() {
...
}
}


First the idea was to add the stubbing in this MyTestConfig configuration class, so that the mock is pre-made for all tests, so I did it in a @PostConstruct method, and it worked just fine - the mock in test did return the expected value:



@PostConstruct
public void init() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


It turned out though, that constructing a pre-made mock suitable for all test can be tricky, so we decided to move the stubbing to tests.



@Test
public void aTest() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


And this doesn't work - the stubbed method returns null. We want to leave MockBeans in the configuration class, but stub them in tests, so any advice on why the stubbing is ineffective?



Spring Boot 2.0.5, Mockito 2.22.0










share|improve this question


















  • 1




    I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
    – M. Deinum
    Nov 23 '18 at 8:08










  • @M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
    – snw
    Nov 23 '18 at 8:38








  • 1




    If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
    – M. Deinum
    Nov 23 '18 at 8:40










  • @M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
    – snw
    Nov 23 '18 at 9:05














0












0








0







I have a configuration class with a few MockBeans replacing actual beans in context for tests.



@Configuration
public class MyTestConfig {
@MockBean
private MyService myService;
}


I use those mocks in my tests:



@Import({ MyTestConfig .class })
public class MyTest {
@Autowired
private MyService myService;

@Test
public void aTest() {
...
}
}


First the idea was to add the stubbing in this MyTestConfig configuration class, so that the mock is pre-made for all tests, so I did it in a @PostConstruct method, and it worked just fine - the mock in test did return the expected value:



@PostConstruct
public void init() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


It turned out though, that constructing a pre-made mock suitable for all test can be tricky, so we decided to move the stubbing to tests.



@Test
public void aTest() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


And this doesn't work - the stubbed method returns null. We want to leave MockBeans in the configuration class, but stub them in tests, so any advice on why the stubbing is ineffective?



Spring Boot 2.0.5, Mockito 2.22.0










share|improve this question













I have a configuration class with a few MockBeans replacing actual beans in context for tests.



@Configuration
public class MyTestConfig {
@MockBean
private MyService myService;
}


I use those mocks in my tests:



@Import({ MyTestConfig .class })
public class MyTest {
@Autowired
private MyService myService;

@Test
public void aTest() {
...
}
}


First the idea was to add the stubbing in this MyTestConfig configuration class, so that the mock is pre-made for all tests, so I did it in a @PostConstruct method, and it worked just fine - the mock in test did return the expected value:



@PostConstruct
public void init() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


It turned out though, that constructing a pre-made mock suitable for all test can be tricky, so we decided to move the stubbing to tests.



@Test
public void aTest() {
when(myService.foo("say hello")).thenReturn("Hello world");
}


And this doesn't work - the stubbed method returns null. We want to leave MockBeans in the configuration class, but stub them in tests, so any advice on why the stubbing is ineffective?



Spring Boot 2.0.5, Mockito 2.22.0







spring spring-boot testing mocking mockito






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 7:36









snw

1,160713




1,160713








  • 1




    I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
    – M. Deinum
    Nov 23 '18 at 8:08










  • @M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
    – snw
    Nov 23 '18 at 8:38








  • 1




    If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
    – M. Deinum
    Nov 23 '18 at 8:40










  • @M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
    – snw
    Nov 23 '18 at 9:05














  • 1




    I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
    – M. Deinum
    Nov 23 '18 at 8:08










  • @M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
    – snw
    Nov 23 '18 at 8:38








  • 1




    If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
    – M. Deinum
    Nov 23 '18 at 8:40










  • @M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
    – snw
    Nov 23 '18 at 9:05








1




1




I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
– M. Deinum
Nov 23 '18 at 8:08




I'm actually surprised that @MockBean works in a configuration class as it shouldn't. Also the use of @Import on your test class is something you shouldn't be doing. If you want to globally mock beans you will need to create the mock yourself using Mockito.mock inside an @Bean method to have reliable mocking. Else use an @Autowired field in your testcase which you want to use the mocked instance. Also instead of @Import you should specify this in your @SpringBootTest or @ContextConfiguration as class to use for configuration.
– M. Deinum
Nov 23 '18 at 8:08












@M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
– snw
Nov 23 '18 at 8:38






@M.Deinum The documentation of @MockBean states: Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner, so it's definitely supposed to work in configuration class. Defining a plain mock in @Bean method would be fine if the stubbing in test worked, but it doesn't, so that's not an option either.
– snw
Nov 23 '18 at 8:38






1




1




If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
– M. Deinum
Nov 23 '18 at 8:40




If stubbing doesn't work you must be doing weird things. We use this literally in hundreds of testcases and works like a charm. Are you defining the correct stubbing for the actions you want to perform?
– M. Deinum
Nov 23 '18 at 8:40












@M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
– snw
Nov 23 '18 at 9:05




@M.Deinum Turns our my problem description is insufficient, because I skipped quite an important detail, but you did help me figure it out anyway. What I didn't say (aiming to keep it simple) is that my test is an @WebMvcTest with @WithUserDetails, and my service is a dependency of a custom UserDetailsManager. Spring Security makes the call to UserDetailsManager before the actual test content. That's why the stubbing in test had no effect, and that's why it worked fine when the mock was stubbed in config's @PostConstruct. Thanks for your help.
– snw
Nov 23 '18 at 9:05












1 Answer
1






active

oldest

votes


















1














Yes, stubbing should be performed inside their respective test cases (unless you have a test class that shares the stubbing scenarios but it all comes down to preference).



However, for creating @MockBeans, you would need to use a @SpringBootTest in order to get the actual beans replaced with mocks. This could be done as simply as this example:



@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

@Autowired
private MyTestClass testClass;
@MockBean
private MyService service;

@Test
public void myTest() {
// testing....
}

}





share|improve this answer





















  • The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
    – snw
    Nov 23 '18 at 8:41






  • 1




    Are you using @SpringBootTest and a SpringRunner to run your tests?
    – Urosh T.
    Nov 23 '18 at 8:48










  • I figured it out, see my comments under the question. Thanks for help!
    – snw
    Nov 23 '18 at 9:06











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%2f53442430%2fmockbean-stubbing-ineffective%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














Yes, stubbing should be performed inside their respective test cases (unless you have a test class that shares the stubbing scenarios but it all comes down to preference).



However, for creating @MockBeans, you would need to use a @SpringBootTest in order to get the actual beans replaced with mocks. This could be done as simply as this example:



@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

@Autowired
private MyTestClass testClass;
@MockBean
private MyService service;

@Test
public void myTest() {
// testing....
}

}





share|improve this answer





















  • The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
    – snw
    Nov 23 '18 at 8:41






  • 1




    Are you using @SpringBootTest and a SpringRunner to run your tests?
    – Urosh T.
    Nov 23 '18 at 8:48










  • I figured it out, see my comments under the question. Thanks for help!
    – snw
    Nov 23 '18 at 9:06
















1














Yes, stubbing should be performed inside their respective test cases (unless you have a test class that shares the stubbing scenarios but it all comes down to preference).



However, for creating @MockBeans, you would need to use a @SpringBootTest in order to get the actual beans replaced with mocks. This could be done as simply as this example:



@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

@Autowired
private MyTestClass testClass;
@MockBean
private MyService service;

@Test
public void myTest() {
// testing....
}

}





share|improve this answer





















  • The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
    – snw
    Nov 23 '18 at 8:41






  • 1




    Are you using @SpringBootTest and a SpringRunner to run your tests?
    – Urosh T.
    Nov 23 '18 at 8:48










  • I figured it out, see my comments under the question. Thanks for help!
    – snw
    Nov 23 '18 at 9:06














1












1








1






Yes, stubbing should be performed inside their respective test cases (unless you have a test class that shares the stubbing scenarios but it all comes down to preference).



However, for creating @MockBeans, you would need to use a @SpringBootTest in order to get the actual beans replaced with mocks. This could be done as simply as this example:



@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

@Autowired
private MyTestClass testClass;
@MockBean
private MyService service;

@Test
public void myTest() {
// testing....
}

}





share|improve this answer












Yes, stubbing should be performed inside their respective test cases (unless you have a test class that shares the stubbing scenarios but it all comes down to preference).



However, for creating @MockBeans, you would need to use a @SpringBootTest in order to get the actual beans replaced with mocks. This could be done as simply as this example:



@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {

@Autowired
private MyTestClass testClass;
@MockBean
private MyService service;

@Test
public void myTest() {
// testing....
}

}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 23 '18 at 8:16









Urosh T.

6261916




6261916












  • The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
    – snw
    Nov 23 '18 at 8:41






  • 1




    Are you using @SpringBootTest and a SpringRunner to run your tests?
    – Urosh T.
    Nov 23 '18 at 8:48










  • I figured it out, see my comments under the question. Thanks for help!
    – snw
    Nov 23 '18 at 9:06


















  • The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
    – snw
    Nov 23 '18 at 8:41






  • 1




    Are you using @SpringBootTest and a SpringRunner to run your tests?
    – Urosh T.
    Nov 23 '18 at 8:48










  • I figured it out, see my comments under the question. Thanks for help!
    – snw
    Nov 23 '18 at 9:06
















The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
– snw
Nov 23 '18 at 8:41




The bean is actually replaced with a mock. MockUtil.isMock(myService) returns true in test. The only issue is that the stubbing performed in test has no effect.
– snw
Nov 23 '18 at 8:41




1




1




Are you using @SpringBootTest and a SpringRunner to run your tests?
– Urosh T.
Nov 23 '18 at 8:48




Are you using @SpringBootTest and a SpringRunner to run your tests?
– Urosh T.
Nov 23 '18 at 8:48












I figured it out, see my comments under the question. Thanks for help!
– snw
Nov 23 '18 at 9:06




I figured it out, see my comments under the question. Thanks for help!
– snw
Nov 23 '18 at 9:06


















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.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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%2f53442430%2fmockbean-stubbing-ineffective%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

What visual should I use to simply compare current year value vs last year in Power BI desktop

How to ignore python UserWarning in pytest?

Alexandru Averescu