Mockito - @Spy vs @Mock

后端 未结 7 877
南旧
南旧 2020-11-29 17:33

Mockito - I understand a spy calls the real methods on an object, while a mock calls methods on the double object. Also spies are to be avoided unless there is a code smell.

相关标签:
7条回答
  • 2020-11-29 18:31

    In short:

    @Spy and @Mock are used heavily in testing of code, but developers do confuse in cases when to use one of them and thus developers end up in using @Mock to be safe.

    • Use @Mock when you want to just test the functionality externally without actually calling that method.
    • Use @Spy when you want to test the functionality externally + internally with the very method being called.

    Below is the example where i have taken the scenario of Election20xx in America.

    Voters can be divided according to VotersOfBelow21 and VotersOfABove21.

    The ideal Exit poll says that Trump will win the election because VotersOfBelow21 and VotersOfABove21 both will vote for trump saying "We elected President Trump "

    But this is not the real scenario:

    Voters of both age group voted for Trump because they had No other effective choice other than Mr Trump.

    So how do you Test it??

    public class VotersOfAbove21 {
    public void weElected(String myVote){
      System.out.println("Voters of above 21 has no Choice Than Thrump in 20XX ");
    }
    }
    

    public class VotersOfBelow21 {
      public void weElected(String myVote){
        System.out.println("Voters of below 21 has no Choice Than Thrump in 20XX");
      }
    }
    

    public class ElectionOfYear20XX {
      VotersOfAbove21 votersOfAbove21;
      VotersOfBelow21 votersOfBelow21;
      public boolean weElected(String WeElectedTrump){
        votersOfAbove21.weElected(WeElectedTrump);
        System.out.println("We elected President Trump ");
    
        votersOfBelow21.weElected(WeElectedTrump);
        System.out.println("We elected President Trump ");
        return true;
      }
    
    }
    

    Now Note in above first two classes, both the age group people says that they do not have a better choice than trump. Which explicitly means that they voted for Trump just because they had no choice.

    Now the ElectionOfYear20XX says that Trump Won because both age group voted for him overwhelmingly.

    If we were to Test the ElectionOfYear20XX with @Mock, then we might not be able to get the real reason why Trump won, we will be just testing the external reason.

    If we test the ElectionOfYear20XX with @Spy, then we get the real reason why Trump won with the external exit poll results, i.e internally + externally.


    Our ELectionOfYear20XX_Test class:

    @RunWith(MockitoJUnitRunner.class)
    public class ELectionOfYear20XX_Test {
    
      @Mock
      VotersOfBelow21 votersOfBelow21;
      @Mock
      VotersOfAbove21 votersOfAbove21;
      @InjectMocks
      ElectionOfYear20XX electionOfYear20XX;
      @Test
      public void testElectionResults(){
        Assert.assertEquals(true,electionOfYear20XX.weElected("No Choice"));
      }
    
    }
    

    This should output just the logic test results i.e. external check:

    We elected President Trump 
    We elected President Trump 
    

    Testing with @Spy externally as well as internally with actual method invocation.

    @RunWith(MockitoJUnitRunner.class)
    public class ELectionOfYear20XX_Test {
    
      @Spy
      VotersOfBelow21 votersOfBelow21;
      @Spy
      VotersOfAbove21 votersOfAbove21;
      @InjectMocks
      ElectionOfYear20XX electionOfYear20XX;
      @Test
      public void testElectionResults(){
        Assert.assertEquals(true,electionOfYear20XX.weElected("No Choice"));
      }
    
    }
    

    Output:

    Voters of above 21 has no Choice Than Thrump in 20XX 
    We elected President Trump 
    Voters of below 21 has no Choice Than Thrump in 20XX
    We elected President Trump 
    
    0 讨论(0)
提交回复
热议问题