Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a builder with mockito

I have a builder:

class Builder{      private String name;      private String address;      public Builder setName(String name){          this.name = name;          return this;     }      public Builder setAddress(String address){          this.address = address;          return this;     }  } 

Mocking the builder in mockito will gives me null for every method. So is there an easy way to get the builder return itself on every function call, without mocking every function itself using when().thenReturn.

like image 651
Andreas Köberle Avatar asked Dec 14 '11 09:12

Andreas Köberle


People also ask

Can Mockito mock constructor?

Starting with Mockito version 3.5. 0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes.

Can Mockito mock a class?

The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called.


2 Answers

The problem with using RETURN_DEEP_STUBS is that you'll get a different mock each time you call a method. I think from your question that you want to use a default Answer that actually returns the mock on which it was called, for each method that has the right return type. This could look something like the following. Note that I haven't tested this, so it may contain typos, but I hope that the intention is clear in any case.

import static org.mockito.Mockito.RETURNS_DEFAULTS; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer;  public class SelfReturningAnswer implements Answer<Object> {      public Object answer(InvocationOnMock invocation) throws Throwable {         Object mock = invocation.getMock();         if(invocation.getMethod().getReturnType().isInstance(mock)){             return mock;         }         return RETURNS_DEFAULTS.answer(invocation);     } } 

Then, when you create your mock, specify this as your default answer. This will make your mock return itself from each method that it can; but it will behave like an ordinary mock when you call a method whose return type is wrong for the mock.

Create your mock like this

Builder mockBuilder = mock( Builder.class, new SelfReturningAnswer()); 

or create a constant for this class and write something like

@Mock(answer = SELF_RETURNING) private Builder mockBuilder; 

Hope that helps.

like image 109
Dawood ibn Kareem Avatar answered Sep 28 '22 02:09

Dawood ibn Kareem


As of Mockito 2.0 (beta), there is a new default answer for RETURNS_SELF that behaves almost identically to David Wallace's answer. Example from the Mockito docs:

@Test public void use_full_builder_with_terminating_method() {     HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);     HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);     String response = "StatusCode: 200";      when(builder.request()).thenReturn(response);      assertThat(requester.request("URI")).isEqualTo(response); } 

Note that it appears both on the Mockito class and on the Answers enum, so it is also be compatible with @Mock(answer = RETURNS_SELF) syntax.

like image 27
Jeff Bowman Avatar answered Sep 28 '22 03:09

Jeff Bowman