0

I wanted to test my controllers, and I have hard time with mocking objects. I have very simple method like this.

@RequestMapping(value = "/places", method = RequestMethod.GET)
public String showPlacesByQuery(Model model, @RequestParam(value = "q", required = false) String query) {

    Location location = geolocationParser.getCoords(query); //this line cause NPE
    List placesList = placeService.findPublicPlaces(location, 0);

    model.addAttribute("query", query);
    model.addAttribute("placesList", placesList);
    return "places/list";
}

I wrote test and I'm getting NullPointerException. I think the cause is that geolocationParser.getCoordS(query) returns null? or something is wrong with whole assignment Location location = geolocationParser.getCoords(query);

@Mock
GeolocationParser geolocationParser;

@Mock
PlaceService placeService;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testShowPlacesByQuery() throws Exception {

    String query = "SomeQuery";
    PlaceController placeController = new PlaceController();

    Location location = mock(Location.class);
    location.setCity("someString");
    location.setLatitude("54.2323");
    location.setLongitude("18.2323");

    when(geolocationParser.getCoords(Mockito.anyString())).thenReturn(location);

    List<Place> expectedPlaces = asList(new Place(), new Place());
    when(placeService.findPublicPlaces(location, 0)).thenReturn(expectedPlaces);

    MockMvc mockMvc = MockMvcBuilders.standaloneSetup(placeController).build();
    mockMvc.perform(get("/places").param("q", query))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(view().name("places/list"));
}

I spend hours to make it work, on different ways, with no results.

Jakub Pomykała
  • 2,082
  • 3
  • 27
  • 58
  • Did you just try by passing `query` instead of anyString()? – Branislav Lazic Nov 24 '15 at 21:23
  • Yup, I was trying to make it work on many possible ways, but still I'm doing something wrong – Jakub Pomykała Nov 24 '15 at 21:24
  • 3
    Also, did you inject mocks into your controller? – Branislav Lazic Nov 24 '15 at 21:25
  • 2
    Have you tried debugging your test? Is `geolocationParser` `null`? Is it a bean? How do you use it normally in the controller? Do you autowire it in? You will have to inject the mocks into the controller. – Vivin Paliath Nov 24 '15 at 21:26
  • Yes, I'm autowireing `GeolocationParser` in controller. This is my own `@Component` class – Jakub Pomykała Nov 24 '15 at 21:33
  • It's not about whether you autowire GeolocationParser in controller. It's about whether you inject mock of GeolocationParser into a controller. – Branislav Lazic Nov 24 '15 at 21:39
  • Where is the `@InjectMocks` tag? `@InjectMocks private PlaceController placeController;` – gonzo Nov 24 '15 at 21:40
  • @gonzo Yup, now I understand this, and you have right. I need to inject mocks into my `PlaceController` now i get it. Please write the answer so I can accept it. Previously I was trying to use `@Mock` annotation on `PlaceController`. Now everything is clear to me. Thank you – Jakub Pomykała Nov 24 '15 at 21:47

2 Answers2

1

I think the problem is that you are not correctly passing in the mocks to your System under test. If you are autowireing you need to have an application context started otherwise it can not inject the class.

Trafalgar
  • 361
  • 1
  • 4
  • 14
1

If you are testing your PlaceController class you should not be creating an instance for that class manually. Use @InjectMocks.

@Mock
private FormServiceImpl formService;

@Mock 
private FormDao formDao;

@InjectMocks
private PlaceController placeController;

And remove it form here

@Test
public void testShowPlacesByQuery() throws Exception {

    String query = "SomeQuery";
    //PlaceController placeController = new PlaceController();
gonzo
  • 2,103
  • 1
  • 15
  • 27