Rito
Rito

Reputation: 3298

Mockito mocking method with class parameter vs actual object parameter

What is the difference between these two as per Mockito -

Mockito.when(serviceObject.myMethod(Customer.class)).thenThrow(new RuntimeException());

and

Customer customer = new Customer(); Mockito.when(serviceObject.myMethod(customer)).thenThrow(new RuntimeException());

And if both serve the same purpose then using which one is considered to be best practice?

Upvotes: 2

Views: 4904

Answers (2)

GhostCat
GhostCat

Reputation: 140525

There is a misunderstanding on your side - that method specification myMethod(SomeClass.class) is only possible when the signature of that method allows for a class parameter. Like:

Whatever myMethod(Object o) {

or directly

Whatever myMethod(Class<X> clazz) {

In other words: it is not Mockito that does something special about a parameter that happens to be of class Class!

Thus your first option is not something that works "in general". Example: I put down this code in a unit test:

static class Inner {
    public int foo(String s) { return 5; }
}

@Test
public void testInner() {
    Inner mocked = mock(Inner.class);
    when(mocked.foo(Object.class)).thenReturn(4);
    System.out.println(mocked.foo(""));
}

And guess what - the above does not compile. Because foo() doesn't allow for a Class parameter. We can rewrite to

static class Inner {
    public int foo(Object o) { return 5; }
}

@Test
public void testInner() {
    Inner mocked = mock(Inner.class);
    when(mocked.foo(Object.class)).thenReturn(4);
    System.out.println(mocked.foo(""));
}

And now the above compiles - but prints 0 (zero) when invoked. Because the above would be the same as mocked.foo(eq(Object.class)). In other words: when your method signature allows for passing a Class instance and you then pass a class instance, that is a simple mocking specification for mockito. In my example: when the incoming object would be Object.class - then 4 would be returned. But the incoming object is "" - therefore the Mockito default kicks in and 0 is returned.

I am with the other answer here - I think you are mixing up that older versions of Mockito asked you to write down when(mocked.foo(any(ExpectedClass.class))) - which can nowadays be written as when(mocked.foo(any())). But when(mocked.foo(ExpectedClass.class)) is not a Mockito construct - it is a simple method specification that gives a specific object to "match on" - and that specific object happens to be an instance of class Class.

Upvotes: 3

JavaYouth
JavaYouth

Reputation: 1552

First one which uses generic Customer class to match type can also be written as:

Mockito.when(serviceObject.myMethod(Mockito.any(Customer.class))).thenThrow(new RuntimeException());

In case of the second one, you are passing the actual object that will be used in stubbing.

Usage:

If your method myMethod throws the exception based on the state of the Customer object then you can use the latter approach, where you can set the state of the Customer object appropriately.

However If your method myMethod does not depend on the Customer object to throw the exception rather you need it only to pass it as an argument just to invoke the method, then you can take the former approach.

Upvotes: 2

Related Questions