Bird
Raised Fist0
JUnittesting~20 mins

@Spy for partial mocking in JUnit - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Spy Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of partial mocking with @Spy
Consider the following JUnit test using Mockito's @Spy annotation. What will be the output of the test method?
JUnit
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    public int multiply(int a, int b) {
        return a * b;
    }
}

@ExtendWith(MockitoExtension.class)
public class CalculatorTest {
    @Spy
    Calculator calculator;

    @Test
    public void testAddAndMultiply() {
        when(calculator.multiply(2, 3)).thenReturn(10);
        int sum = calculator.add(2, 3);
        int product = calculator.multiply(2, 3);
        System.out.println("Sum: " + sum);
        System.out.println("Product: " + product);
    }
}
ASum: 0\nProduct: 6
BSum: 5\nProduct: 10
CSum: 0\nProduct: 10
DSum: 5\nProduct: 6
Attempts:
2 left
💡 Hint
Remember that @Spy calls real methods unless stubbed.
❓ assertion
intermediate
1:30remaining
Correct assertion for verifying @Spy behavior
Given a @Spy object of class Service with a method fetchData(), which assertion correctly verifies that fetchData() was called exactly once?
JUnit
@Spy
Service service;

@Test
public void testFetchData() {
    service.fetchData();
    // Which assertion is correct here?
}
Averify(service, times(1)).fetchData();
Bverify(service).fetchData(1);
CassertEquals(1, service.fetchData());
Dverify(service, once()).fetchData();
Attempts:
2 left
💡 Hint
Use Mockito's verify method with times() for call count.
🔧 Debug
advanced
2:30remaining
Debugging unexpected behavior with @Spy
A test uses @Spy on a List object. The test stubs the size() method to return 5, but the real size() method is called (returning 0) during stubbing. What is the most likely cause?
JUnit
@Spy
List<String> spyList = new ArrayList<>();

@Test
public void testSize() {
    when(spyList.size()).thenReturn(5);
    int size = spyList.size();
    System.out.println(size);
}
AThe spyList was not initialized properly before stubbing.
BThe when() method was called before the spy was created.
CThe stubbing should use doReturn(5).when(spyList).size() instead of when().thenReturn().
DThe size() method cannot be stubbed on a spy.
Attempts:
2 left
💡 Hint
When stubbing spy methods, some methods require doReturn() style stubbing.
🧠 Conceptual
advanced
1:30remaining
Understanding @Spy vs @Mock behavior
Which statement best describes the difference between @Spy and @Mock in Mockito?
A@Spy creates a full mock with no real method calls; @Mock creates a partial mock that calls real methods unless stubbed.
B@Spy disables all method calls; @Mock calls real methods by default.
C@Spy and @Mock behave identically; both call real methods unless stubbed.
D@Spy creates a partial mock that calls real methods unless stubbed; @Mock creates a full mock with no real method calls.
Attempts:
2 left
💡 Hint
Think about which mock type calls real methods by default.
❓ framework
expert
3:00remaining
Best practice for using @Spy with constructor arguments
You want to create a @Spy instance of a class Service that requires constructor arguments. Which approach correctly initializes the spy in a JUnit 5 test with Mockito?
A
@Spy
Service service = new Service("arg1", 10);
B
@Spy
Service service;

@BeforeEach
public void setup() {
    service = spy(new Service("arg1", 10));
}
C
@Spy
Service service = mock(Service.class);
D
@Spy
Service service;

@BeforeEach
public void setup() {
    service = mock(Service.class, withSettings().useConstructor("arg1", 10).defaultAnswer(CALLS_REAL_METHODS));
}
Attempts:
2 left
💡 Hint
Use field initializer to construct the real instance with args for @Spy.

Practice

(1/5)
1. What does the @Spy annotation do in JUnit testing?
easy
A. Automatically runs all test methods in a class.
B. Creates a completely fake object with no real method calls.
C. Creates a real object but allows overriding some methods for partial mocking.
D. Mocks static methods of a class.

Solution

  1. Step 1: Understand @Spy purpose

    @Spy creates a real instance of the class but allows selective method overriding.
  2. Step 2: Compare with other mocking types

    Unlike full mocks, spies call real methods unless stubbed.
  3. Final Answer:

    Creates a real object but allows overriding some methods for partial mocking. -> Option C
  4. Quick Check:

    @Spy = Partial real object with override [OK]
Hint: Remember: @Spy means real object with some fake methods [OK]
Common Mistakes:
  • Confusing @Spy with @Mock which creates full fake objects
  • Thinking @Spy mocks static methods
  • Assuming @Spy runs tests automatically
2. Which of the following is the correct way to initialize a spy object in a JUnit 5 test class using Mockito?
easy
A. @Spy MyClass mySpy; MockitoAnnotations.openMocks(this);
B. @Spy MyClass mySpy = new MyClass();
C. @Spy MyClass mySpy = Mockito.mock(MyClass.class);
D. @Spy MyClass mySpy = Mockito.spy(null);

Solution

  1. Step 1: Recognize proper spy initialization

    Using @Spy requires calling MockitoAnnotations.openMocks(this) to initialize the spy fields.
  2. Step 2: Check other options

    @Spy MyClass mySpy = new MyClass(); misses initialization call; C uses mock instead of spy; D tries spying on null which is invalid.
  3. Final Answer:

    @Spy MyClass mySpy; MockitoAnnotations.openMocks(this); -> Option A
  4. Quick Check:

    Initialize spies with openMocks(this) [OK]
Hint: Always call MockitoAnnotations.openMocks(this) to init @Spy [OK]
Common Mistakes:
  • Not calling MockitoAnnotations.openMocks(this)
  • Confusing spy creation with mock creation
  • Trying to spy on null or uninitialized objects
3. Given the following code snippet, what will be the output of the test?
@Spy
List<String> spyList = new ArrayList<>();

@Test
void testSpyList() {
    spyList.add("one");
    spyList.add("two");
    Mockito.doReturn(100).when(spyList).size();
    System.out.println(spyList.size());
}
medium
A. 2
B. 100
C. 0
D. Throws NullPointerException

Solution

  1. Step 1: Understand spy behavior with doReturn

    The spy calls real methods unless stubbed. Here, size() is stubbed to return 100.
  2. Step 2: Analyze output of spyList.size()

    Despite adding two elements, size() returns 100 due to stubbing.
  3. Final Answer:

    100 -> Option B
  4. Quick Check:

    Stubbed spy method returns stub value [OK]
Hint: Stub spy methods with doReturn to override real calls [OK]
Common Mistakes:
  • Expecting real method size() to return actual list size
  • Using when(spyList.size()) instead of doReturn for spies
  • Forgetting spy initialization causing NullPointerException
4. Identify the error in the following test code using @Spy:
@Spy
MyService service;

@Test
void testService() {
    service = new MyService();
    Mockito.doReturn("mocked").when(service).getData();
    assertEquals("mocked", service.getData());
}
medium
A. The spy object is not initialized with MockitoAnnotations.openMocks(this).
B. You cannot assign a new instance to a @Spy annotated field.
C. doReturn cannot be used with spy objects.
D. The assertEquals method is used incorrectly.

Solution

  1. Step 1: Check spy initialization

    The @Spy field must be initialized by calling MockitoAnnotations.openMocks(this) before use.
  2. Step 2: Analyze assignment and usage

    Assigning new instance manually is allowed but without initialization, spy won't work properly.
  3. Final Answer:

    The spy object is not initialized with MockitoAnnotations.openMocks(this). -> Option A
  4. Quick Check:

    Always init @Spy with openMocks(this) [OK]
Hint: Always initialize @Spy fields before test runs [OK]
Common Mistakes:
  • Forgetting to call MockitoAnnotations.openMocks(this)
  • Thinking manual assignment replaces initialization
  • Believing doReturn can't be used with spies
5. You want to partially mock a complex service class PaymentProcessor to test only the processPayment() method while keeping other methods real. Which approach using @Spy is best to achieve this?
hard
A. Create a new PaymentProcessor instance without @Spy and call processPayment() directly.
B. Mock the entire PaymentProcessor class with @Mock and implement processPayment() manually.
C. Use @Spy but override all methods except processPayment() to avoid side effects.
D. Create a spy of PaymentProcessor and stub only processPayment() method with Mockito.doReturn().

Solution

  1. Step 1: Understand partial mocking goal

    Partial mocking means real methods run except those stubbed.
  2. Step 2: Choose spy with selective stubbing

    Using @Spy and stubbing only processPayment() lets you test that method while others behave normally.
  3. Step 3: Evaluate other options

    Mocking entire class loses real behavior; overriding all except one is complex; no spy means no partial mocking.
  4. Final Answer:

    Create a spy of PaymentProcessor and stub only processPayment() method with Mockito.doReturn(). -> Option D
  5. Quick Check:

    @Spy + stub target method = partial mocking [OK]
Hint: Spy real object, stub only target method for partial mocking [OK]
Common Mistakes:
  • Mocking entire class losing real method calls
  • Overriding too many methods manually
  • Not using @Spy for partial mocking
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard