2

I'm trying to unit test ClassA(String) constructor of following ClassA class:

import ExternalObject;

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(String string) {
        super();
        this.externalObject = new ExternalObject().parseString(string);
    }
}

I want to mock the new ExternalObject().parseString(string) call and stub it with a sample ExternalObject object.

I've looked into Mockito, but it seems this task isn't possible with Mockito because:

Is it possible to do this in Mockito (or any other mocking library) without rewriting a lot of code? I'm open to small code changes to make it more test-friendly.

narendra-choudhary
  • 4,582
  • 4
  • 38
  • 58

1 Answers1

5

In order to mock the ExternalObject you have to be able to supply the instance of ExternalObject which is used in your test flow.

That's going to be difficult as long as the ExternalObject is created inside public ClassA(String string).

In order to make your ClassA more testable you'll need to be able to provide an instance of ExternalObject when constructing ClassA.

For example:

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(ExternalObject externalObject, String string) {
        super();
        this.externalObject = externalObject.parseString(string);
    }
}

This can be then tested as follows:

public class ClasssATest {

    @Test
    public void someTest() {
        String input = "a string";
        ExternalObject externalObject = Mockito.mock(ExternalObject.class);
        Mockito.when(externalObject.parseString(eq(input))).thenReturn(externalObject);

        ClassA sut = new ClassA(externalObject, input);
        ...
    }
}

The key point here is: inject the external dependency into your class. Once you make this change, testing becomes much easier and, more generally, this approach makes it easier to change system behaviour by swapping in/out implementations of that external dependency.

glytching
  • 44,936
  • 9
  • 114
  • 120
  • 1
    Shouldn't `Mockito.when(externalObject.parseString()).thenReturn("some string");` be `Mockito.when(externalObject.parseString("some string")).thenReturn(externalObject);`? – narendra-choudhary Jan 29 '18 at 09:53
  • @glytching Why do you use `Mockito.eq()` ? It seems not required here. – davidxxx Jan 29 '18 at 10:03
  • Agreed, not required for a `String` argument. Force of habit, I guess. – glytching Jan 29 '18 at 10:04
  • @glytching just for the recores: `Mockito.eq()` is not needed because you compare with the same object (one that qualifies to return `true` when its `equals()` method is called). That would also work with a custom object if the *same instance* is passed along by the cut or with a DTO created inside the cut having an `equals()` implementation. – Timothy Truckle Jan 31 '18 at 08:54