简体   繁体   English

Mockito在模拟调用中验证对模拟方法的调用

[英]Mockito verify the call to a mock method inside a mock call

I have model mock class where i verify a call from another DAO mock object. 我有模型模拟类,在其中可以验证来自另一个DAO模拟对象的调用。 But this call is not happening to model class and only verify happens on DAO class. 但是此调用不会在模型类上发生,而仅在DAO类上进行验证。

public class ApplicationTests {

@Mock
private Card card; 

@Mock
private JourneyDAO journeyDAO;

@InjectMocks
private JourneyServiceImpl journeyServiceImpl;

private static final Double ZERO_VALUE = 0.0;
private static final Double INITIAL_BALANCE = 30D;
private static final String NAME = "name";

@Before
public void setUp() {
    when(card.getBalance()).thenReturn(INITIAL_BALANCE);
    when(card.getName()).thenReturn(NAME);
}


@Test
public void startJourneyInZone1_Test() {
    barrier = new Barrier(card, direction.IN, journeyType.TUBE, Stations.Holborn);
    journeyServiceImpl.startTubeJourney(barrier);
    verify(card, times(1)).addBalance(MAX_FARE * -1);// this call is not heppening
    verify(journeyDAO, times(1)).startTubeJourney(barrier);// this is working 
}

}

DAO class method looks like as below DAO类的方法如下图

public void startTubeJourney(Barrier barrier) {
    if(barrier.getModeOfJourney() == TravelMode.TUBE) {
        if(barrier.getDirection() == Direction.IN) {
            boardingAtZone = barrier.getZone();
            barrier.getCard().addBalance(MAX_FARE * -1);
        }
    }
}

I am getting below error while running the Test. 运行测试时出现错误提示。 Please ignore the package and class names mismatch as i am making some example case. 请忽略包和类名不匹配的情况,因为我正在举一些示例案例。

Wanted but not invoked:
card.addBalance(0.7000000000000002d);
-> at com.rcard.travel.ApplicationTests.endTubeJourneyTest(ApplicationTests.java:69)

Actually, there were zero interactions with this mock.

at com.travel.ApplicationTests.endTubeJourneyTest(ApplicationTests.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Barrier class looks like 屏障类看起来像

public class Barrier {

    private Card card;
    private Direction direction;
    private TravelMode modeOfJourney;
    private Stations zone;

    public Barrier(Card card, Direction direction, TravelMode mode, Stations zone) {
        this.card = card;
        this.direction = direction;
        this.modeOfJourney = mode;
        this.zone = zone;
    }

    public String getZone() {
        return Stations.elementOf(this.zone);
    }

    public void setZone(Stations zone) {
        this.zone = zone;
    }

    public Card getCard() {
        return card;
    }

    public void setCard(Card card) {
        this.card = card;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    public TravelMode getModeOfJourney() {
        return modeOfJourney;
    }

    public void setModeOfJourney(TravelMode modeOfJourney) {
        this.modeOfJourney = modeOfJourney;
    }  

}

Because journeyDAO is a mock, this means the real journeyDAO.startTubeJourney() is not being called. 由于journeyDAO是一个模拟,因此这意味着未调用真实的journeyDAO.startTubeJourney()

One possible fix would be to use a real JourneyDAO , so card.addBalance() does get called, but this does mean the one test is testing both the service and DAO classes. 一种可能的解决方法是使用一个真正的JourneyDAO ,因此card.addBalance()确实会被调用,但这确实意味着一个测试正在测试服务类和DAO类。

Alternatively, I would be tempted to write a separate test for JourneyDAO . 另外,我很想为JourneyDAO编写一个单独的测试。 This could call its startTubeJourney() , and verify the card.addBalance() . 这可以调用其startTubeJourney() ,并验证card.addBalance() This would mean the current verify() against the mock journeyDAO.startTubeJourney() could stay. 这意味着针对模拟journeyDAO.startTubeJourney()的当前verify() journeyDAO.startTubeJourney()可以保留。

The issue is with the line 问题在于线

@Mock
private JourneyDAO journeyDAO;

You are trying to verify the method that belongs to mocked object journeyDAO . 您正在尝试验证属于journeyDAO对象journeyDAO If you want to have when...then as well as call real method when it's available, you need to use @Spy annotation. 如果您想拥有when...then在可用时调用真实方法,则需要使用@Spy注释。

@Spy
private JourneyDAO journeyDAO;

will fix the issue. 将解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM