Search code examples
javaunit-testingmockitoobjectinputstream

Mocking an ObjectInputStream


When i try to mock ObjectInputStream object i get a NullPointerException. More precisely, when this line is called: when(inputStream.readObject()).thenReturn(new Person("Doe", "John", "123"));

Code fragment:

@RunWith(MockitoJUnitRunner.class)
public class ConnectionTest{
  ...
  @Mock
  private ObjectInputStream inputStream;
  ...
  @Test
  public void test(){
   ...
    when(inputStream.readObject()).thenReturn(new Person("Doe", "John", "123"));
  ...
  }
}

Normally, when you initialize ObjectInputStream you have to pass an InputStream object as a constructor argument and i bet this is the problem here - there's no InputStream assigned to the ObjectInputStream.

How should i mock the ObjectInputStream properly then?


Solution

  • This is caused by the fact that readObject() is final.

    Mockito can't mock final methods. So what happens is that the attempt to specify that call for the mock object ... simply goes wrong. And yes, the fact that an NPE gets thrown is more than misleading.

    You can try to use that experimental feature in Mockito 2 that allows mocking final methods. If that doesn't work for you, PowerMock(ito) or JMockit most likely would do the job.

    And just for the record: such subtle problems are yet another good reason to not use Java built-in serialization any more.

    The only other way to bypass this: program against the corresponding interface ObjectInput, not the specific implementation class.

    As you can easily mock that interface.

    But of course, that means changing your production code. Which might not be a bad idea, as it decouples your business logic from the actual form of serialization. If you later choose to serialize as JSON strings, using GSON - you would just replace the implementation of that interface.