Oleg Kuts
Oleg Kuts

Reputation: 829

Unable to mock Service layer in Spring MVC Controller mockito testing

I'm unable to mock my NoteService layer when testing my NoteController. When running, the real method noteService.findById(Long id, String login)) is called, instead of mocked one, so I run into NullPointerException. I use Spring Boot 1.33.

Here id my NoteController

@Controller
@RequestMapping("/notes")
public class NoteController {
    @Autowired
    private NoteService noteService;

    @ModelAttribute("noteForm")
    public NoteForm noteForm() {
        return new NoteForm();
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
    public String editNote(@PathVariable("id") Long id, NoteForm noteForm, Principal principal) {
        Note note = noteService.findById(id, principal.getName());
        noteForm.setNote(note);
        noteForm.setAddress(note.getAddress());
        return "edit";
    }       
}

My NoteControllerTest class

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = PhonebookApplication.class)
@WebAppConfiguration
public class NoteControllerTest {

    @Mock
    NoteService noteService;
    @Mock
    View mockView;

    @InjectMocks
    NoteController controller;

    MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mockMvc = standaloneSetup(controller).setSingleView(mockView).build();

    }


    @Test
    public void editNote() throws Exception {
        Long id = 1L;
        Note note = new Note();
        when(noteService.findById(id, "user")).thenReturn(note);
        mockMvc.perform(get("/notes/edit/{id}", id)).andExpect(status().isOk()).andExpect(view().name("edit"));

    }
}

Exception stack trace

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at com.lardi.controller.NoteController.editNote(NoteController.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
at com.lardi.controller.NoteControllerTest.editNote(NoteControllerTest.java:62)

PhonebookApplication - is my main class. (NoteController.java:46) corresponds to my controller line Note note = noteService.findById(id, principal.getName()); I have read this post, but didn't find solution.

Thanks.

Update

I've found the reason. It is my when(noteService.findById(id, "user")).thenReturn(note); stub. It doesn't intercept controllers Note note = noteService.findById(id, principal.getName()); call. But still I don't know how to overcome it, changing when(noteServiceMock.findById(id, any(String.class))).thenReturn(note); causes The method any(Class<String>) is ambiguous for the type NoteControllerTest error. I need to intersect that call properly.

Upvotes: 0

Views: 5715

Answers (2)

Umang Singh
Umang Singh

Reputation: 1

Use @MockBean instead with SpringJUnit4ClassRunner. Basically the object in the controller context changes . When you do MockBean that is taken care .

@MockBean NoteService noteService;

Upvotes: 0

ndrone
ndrone

Reputation: 3572

If I remember correctly if your are using the @Mock and @InjectMocks annotations you must use the MockitoJUnitRunner see the javadocs here: http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/runners/MockitoJUnitRunner.html

so change: @RunWith(SpringJUnit4ClassRunner.class)

to: @RunWith(MockitoJUnitRunner.class)

Upvotes: 1

Related Questions