0

I couldn't find any post related to my problem. I'm using Mockito and I want to test the behavior inside a controller. I think the core of the problem is that I'm not using Mockito correctly when I send in two arguments to the mocked interface. It works fine if I only send in one argument. I don't think the fact that I'm also using Spring mock mvc has anything to do with this.

I have an interface MyService:

public MyObject doSomeDoggyStuff(long id, SomeOtherObject soo);

The purpose of the interface is to do things and return MyObject if it was successful. If it can't find the object then just return null.

I have a controller MyController:

@RestController
@RequestMapping(value = "/dogs")
public MyController
<snip>

 @RequestMapping(method = RequestMethod.POST, value = "/{id}/toys/{toy}")
  ResponseEntity<MyObject> doDoggyStuff(@PathVariable Long id, @RequestBody Toy toy) {
    MyObject result = this.myService.doSomeDoggyStuff(id, toy);
    if(result == null) {
       return new ResponseEntity("errorinfo", HttpStatus.NOT_FOUND);
     }
    else {
      return new ResponseEntity<MyObject>(result,HttpStatus.CREATED)'
     }
  }

My test class looks like this:

Public MyControllerTest <snip>

  @Mock
  private MyService myServiceMock;

  @InjectMocks
  private MyController myController;

The relevant logic of test method looks this.

MyObject myObj = new MyObject();
Toy toy = new Toy();

when(myServiceMock.doSomeDoggyStuff(1, toy)).thenReturn(myObj);
mockMvc
    .perform(
        post("/dogs/{id}/toys/{toys}", 1, toy).contentType(
            TestUtil.APPLICATION_JSON_UTF8).content(
            TestUtil.convertObjectToJsonBytes(toy))).andExpect(status().isCreated())
    .andReturn();

The problem I'm having is that I expect in this scenario that when it tests MyController that on the line: MyObject result = this.myService.doSomeDoggyStuff(id, toy);

result should be the myObj I set up in the thenReturn but it's always set to null. I have other methods in my service that just accepts one argument and it works fine. I can't grasp what I need to do differently when I send in two arguments using Mockito.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
Magnus Lassi
  • 921
  • 2
  • 9
  • 21
  • Did you try to debug what's being passed to the service method call actually? It might be lack of equals implemention in Toy class. Can you post the Toy class code? – makasprzak Jun 20 '14 at 14:32

2 Answers2

1

If I understand your requirements correctly you should use the mock like this:

when(myServiceMock.doSomeDoggyStuff(eq(1), any(Toy.class))).thenReturn(myObj);

The way you have written your code, the mock will return myObj only when called with the Toy object which you instantiated it with, which is never since Spring will instantiate the class on it's own. The problem doesn't have anything to do with the number of arguments.

If however you want to test for a specific Toy and not just any instance of it, you will need to add an equals (and to be correct with the spec, a hashCode) method so mockito can match the Toys. In the absence of any equals method, the references are checked and of couse those are not equals because the instances are not the same.

geoand
  • 60,071
  • 24
  • 172
  • 190
  • This way the test is not testing what Magnus wanted to test - it will pass for whatever Toy object. I believe the problem is with the lack of equals implementation in Toy. – makasprzak Jun 20 '14 at 14:34
  • @macias You might very well be right! That is why I added the first sentence :). I will update the answer accordingly – geoand Jun 20 '14 at 14:38
  • Thank you both! That works beautifully. Mockito is awesome but sometimes it's a little confusing to get the syntax correct for certain scenarios. – Magnus Lassi Jun 20 '14 at 15:21
0

You need to either implement equals in your Toy or use ArgumentCaptor to check details of the object passed. Otherwise (like geoand already managed to mention) you compare the references.

makasprzak
  • 5,082
  • 3
  • 30
  • 49