Contents

Mockito Create Spy

Introduction

With mockito, you can not only create mocks but also spies. A spy behaves the same as a real/normal instance of a class, but mockito tracks all the interactions that happen with the spy.

Create a spy with Mockito

You create a spy by calling the mockito.spy() method with the instance you want to spy on as a parameter. In the following example, I create a spy of the dog instance on line 6. Mockito can use the spy to track the interactions that happen with the instance.

In the example, the bark() method is called and I can use the mockito.verify() to check if this interaction has happened.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class Spying {

    @Test
    void createSpy(){
        Dog myDog = new Dog();
        Dog spyDog = Mockito.spy(myDog);

        spyDog.bark();

        Mockito.verify(spyDog).bark();
    }
}

class Dog {

    public String bark(){
        return "Barking";
    }
}

Create a spy using @spy annotation

We can make the test more readable by using Mockito's annotation @Spy. On lines 7 and 8 in the following example, I create an instance and a spy of the Dog class on a single line. Inside the test method, I can directly use the spy.

Read this article if you want to know more about using Mockito's annotations with JUnit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// use with Mockito 4 / JUnit 4
// @RunWith(MockitoJUnitRunner.class)
// use with mockito 5 / Junit 5
@ExtendWith(MockitoExtension.class)
public class Spying {

    @Spy
    Dog spyDog = new Dog();

    @Test
    void createSpy(){
        spyDog.bark();
        
        Mockito.verify(spyDog).bark();
    }
}

class Dog {

    public String bark(){
        return "Barking";
    }
}

Alter behavior of a spy

You can also stub methods calls just as you do with mocks. In the following example, I use the spy of the dog instance to stub a method. On line 9, I stub the bark() method and make it return a different value than the original.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@ExtendWith(MockitoExtension.class)
public class Spying {

    @Spy
    Dog spyDog = new Dog();

    @Test
    void createSpy(){
        Mockito.when(spyDog.bark()).thenReturn("i am spying");
        String bark = spyDog.bark();

        Mockito.verify(spyDog).bark();
        Assertions.assertEquals("i am spying", bark);
    }
}

class Dog {

    public String bark(){
        return "Barking";
    }
}

Difference with mocks

Mockito tracks the behavior of your objects when you either create a mock of a spy. The biggest difference lies in its default behavior. When you create a mock every call is stubbed and returns null by default and not calling any real object. When you create a spy every method by default calls the real instance.

Depending on the default behavior you need to choose whichever works best for your use case.

Conclusion

This post shows how to create a spy using an existing instance by calling the Mockito.spy method. to make the test more readable you can also use the annotation @spy to create a spy. The last example shows that you can stub method calls to a spy instance.

Further reading

More about testing in Java:

Join the discussion: follow me on Twitter and share your thoughts

This post is just the beginning. If you're interested in learning more, be sure to follow me on Twitter . And if you have any questions or ideas, don't hesitate to reach out via Twitter or send me an email. I'm always happy to connect and continue the conversation.