Search code examples
javaspring-bootspring-testspring-restcontrollerspringmockito

Impossible to write integration test controller with DAO mock?


I become crazy, I tried all possible combination of various test Runners and possibles annotation for testing, the nearest solution of my need is following :

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyApplication.class})
@WebAppConfiguration
public class MyControllerTest {

    MockMvc mockMvc;

    // My DAO is an interface extending JpaRepository
    @Mock
    MyDAO myDAO;

    @Autowired
    WebApplicationContext webApplicationContext;

    @Before
    public void setUp() throws Exception {
        List<MyItem> myItems = new ArrayList(){{
            // Items init ...
        }}
        Mockito.when(myDAO.findAll()).thenReturn(myItems);
        /* Other solution I tried with different annotations: 
        * given(myDAO.findAll()).willReturn(myItems);
        * this.mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
        */
        this.mockMvc = webAppContextSetup(webApplicationContext).build();

    }

    @After
    public void tearDown() throws Exception {
//        Mockito.reset(myDAO);
    }

    @Test
    public void getItems() {
        String res = mockMvc.perform(get("/items"))/*.andExpect(status().isOk())*/.andReturn().getResponse().getContentAsString();
        assertThat(res, is("TODO : string representation of myItems ..."));
        assertNull(res); // For checking change in test functionning
    }
}

I well enter in debug mode in my controller method, in service method but when I see DAO type, it is not a Mock and findAll() always return empty ArrayList(), even when I do :

Mockito.when(myDAO.findAll()).thenReturn(myItems);

I do not have exception raised, my DAO is not mocked and I don't know how to do despite all tuto I found. The nearest tuto of my need I found was this Unit Test Controllers with Spring MVC Test but not enought because he wants mock service injected into controller in order to test controller, I wand to mock DAO injected into real Service injected into Controller (I want to test Controller + Service).

It seems to me that I already did that by using an annotation on the test class which specified what class had to be instanciate by spring application in test mode and what class had to be mocked but I don't remember '-_-.

Need your help, its making me crasy !

Thank you very much !!!


Solution

  • I finally did like that (but not satisfied because it does not mock HSQLDB DataBase, it creates a test one), whereas I wanted to mock DAO :

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {MySpringApplication.class})
    @WebAppConfiguration
    public myTestClass {
        MockMvc mockMvc;
    
        @Autowired
        ItemDAO itemDAO;
    
        @Autowired
        WebApplicationContext webApplicationContext;
    
        @Before
        public void setUp() throws Exception {
            this.mockMvc = webAppContextSetup(webApplicationContext).build();
        }
    
        @After
        public void tearDown() throws Exception {
            itemDAO.deleteAll();
        }
    
        @Test
        public void testMethod() {
            // DB init by saving objects: create a item and save it via DAO, use real test DB
    
            // Only mocking about rest call:
            String res = mockMvc.perform(get("/items")).andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
        }
    

    }