Using @MockBean on test fields is a very succinct way to mock components.
At the moment, it only works with JUnit tests via SpringRunner.
It would be great if it also worked with TestNG via AbstractTestNGSpringContextTests.
@SpringBootTest
public class TestNGMockBeanTest extends AbstractTestNGSpringContextTests {
@MockBean
DemoComponent demoComponent;
@Test
public void mockBeanShouldWork() {
assertTrue(demoComponent != null, "demoComponent is null");
assertTrue(new MockUtil().isMock(demoComponent), "demoComponent is not a mock");
}
}
Desired behaviour: Test passes.
Current behaviour: "demoComponent is null" assertion triggers.
I have the same problem. Unfortunately adding a name attribute to annotation @MockBean as suggested in this blog post doesn't help.
@Krasnyanskiy: Consider using @MockBean like this instead as a workaround:
@SpringBootTest
public class TestNGMockBeanWorkaroundTest extends AbstractTestNGSpringContextTests {
@TestConfiguration
static class Conf {
@MockBean
DemoComponent demoComponent;
}
@Autowired
DemoComponent demoComponent;
@Test
public void mockBeanShouldWork() {
assertTrue(demoComponent != null, "demoComponent is null");
assertTrue(new MockUtil().isMock(demoComponent), "demoComponent is not a mock");
}
}
Well, it's a very weird workaround. In my case Spring is still cannot inject a bean.
there is another workaround : just add @Autowired with @MockBeans and also add a manual reset since the automatic reset does not work
So the following will work :
@SpringBootTest(classes = AppConfig.class)
public @Log class ServiceDrhImplTest_TestNG extends AbstractTestNGSpringContextTests {
private @Autowired ServiceDrh serviceDrh;
private @MockBean @Autowired EmployeDao employeDao;
private @MockBean @Autowired SalaireDao salaireDao;
@AfterMethod
public void afterMethod() {
Mockito.reset(employeDao, salaireDao);
}
But i could not make @BeforeTest and @BeforeSuite work => in those cases I don't have any DI of spring beans
But i could not make @BeforeTest and @BeforeSuite work => in those cases I don't have any DI of spring beans
That's expected.
Look at the source code of AbstractTestNGSpringContextTests.
If you want to have DI _before_ the @BeforeMethod lifecycle callbacks, you will have to implement your own version of AbstractTestNGSpringContextTests.
@qerub I found another workaround. I changed WebMockTest which is in Testing the Web Layer like this:
@WebMvcTest(GreetingController.class)
@TestExecutionListeners(MockitoTestExecutionListener.class)
@Test
public class WebMockTestNg extends AbstractTestNGSpringContextTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private GreetingService service;
@Test
public void greetingShouldReturnMessageFromService() throws Exception {
when(service.greet()).thenReturn("Hello Mock");
this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello Mock")));
}
}
or like below:
@SpringBootTest(classes = GreetingController.class)
@AutoConfigureWebMvc
@AutoConfigureMockMvc
@TestExecutionListeners(MockitoTestExecutionListener.class)
public class WebMockTestNg extends AbstractTestNGSpringContextTests {
// ...
}
The key is to add @TestExecutionListeners(MockitoTestExecutionListener.class).
I met this same issue when use @SpringBootTest + JUnit5 + Mockito.
I found the above two solutions both work, thank you for your solutions.
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {
...
public HelloServiceTest extends BaseTest {
@MockBean
@Autowired
private WorldService worldService;
@Autowired
private HelloService helloService;
@Test
public void testGetStrings() {
Mockito.when(worldService.getWorlds("James")).thenReturn(Arrays.asList("Bob!!!!"));
System.out.println(helloService.getStrings("James"));
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@TestExecutionListeners(MockitoTestExecutionListener.class)
public abstract class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {
...
public HelloServiceTest extends BaseTest {
@MockBean
private WorldService worldService;
@Autowired
private HelloService helloService;
@Test
public void testGetStrings() {
Mockito.when(worldService.getWorlds("James")).thenReturn(Arrays.asList("Bob!!!!"));
System.out.println(helloService.getStrings("James"));
@uniquejava, if you're writing your tests using JUnit Jupiter (i.e., JUnit 5), you ideally should not be extending AbstractTransactionalJUnit4SpringContextTests since that...
TestExecutionListeners including any of those provided by Spring Boot Test such as the MockitoTestExecutionListenerWhat happens if you completely remove the @TestExecutionListeners declaration, annotate your base test class with @Transactional, and stop extending AbstractTransactionalJUnit4SpringContextTests?
Most helpful comment
@qerub I found another workaround. I changed
WebMockTestwhich is in Testing the Web Layer like this:or like below:
The key is to add
@TestExecutionListeners(MockitoTestExecutionListener.class).