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...
TestExecutionListener
s including any of those provided by Spring Boot Test such as the MockitoTestExecutionListener
What 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
WebMockTest
which is in Testing the Web Layer like this:or like below:
The key is to add
@TestExecutionListeners(MockitoTestExecutionListener.class)
.