Michael Rountree
Michael Rountree

Reputation: 325

Is it possible to Declare but not Instatiate a Spied Object in Mockito using @Spy Notation?

I am writing some JUnit tests for legacy code and I am a big fan of using annotations. I would like to know if it is possible to create a declaration to a spied object and later instantiate it. The reason I ask is because I have a class with a non-null constructor. The values for this constructor are not known until after setup of the test cases. The code below shows what I would like to do:

@RunWith(MockitoJUnitRunner.class)
public class ObjectUndertestTest {

    @Spy private SomeClassToSpy someClassToSpy; 
    private Integer parameterOne;
    private Integer parameterTwo;

    @Before
    public void setupTest() {
        parameterOne = 1;
        parameterTwo = 2;
        someClassToSpy = new SomeClassToSpy(parameterOne, parameterTwo);
    }
}

The only way that I can see to be able to do this is to mix my syntax and use the traditional spy(object to mock) notation. That is:

@RunWith(MockitoJUnitRunner.class)
public class ObjectUndertestTest {

    private SomeClassToSpy someClassToSpy; 
    private Integer parameterOne;
    private Integer parameterTwo;

    @Before
    public void setupTest() {
        parameterOne = 1;
        parameterTwo = 2;
        someClassToSpy = new SomeClassToSpy(parameterOne, parameterTwo);
        SomeClassToSpy spySomeClassToSpy spy(someClassToSpy);
    }
}

Or something similar. Any thoughts on this?

Upvotes: 1

Views: 757

Answers (1)

Jeff Bowman
Jeff Bowman

Reputation: 95614

Beware that @Spy isn't really a documentation annotation: It is an instruction for MockitoJUnitRunner (et al) to initialize the spy automatically for you according to its documented usage patterns. Though annotations are useful and informative, I think it may cause more confusion to use the annotation for its name and not its semantics.

That said, if it's just a matter of constructing an instance with your chosen constructor arguments, you can call the constructor directly and explicitly and use Mockito's initialization to wrap it in a spy (as in the @Spy docs):

@Spy private SomeClassToSpy someClassToSpy = new SomeClassToSpy(1, 2);

Though you'd be right to favor @Before methods over class initializers or constructors, this is an explicitly-documented method of initialization and one unlikely to cause test pollution or initialization-order problems.

Upvotes: 1

Related Questions