简体   繁体   English

如何使用Mockito间谍重定向方法调用?

[英]how to use mockito spy to redirect a method call?

I have a method that relies on "now" Date object. 我有一个依靠“现在”日期对象的方法。

I want to write a unit-test for it. 我想为此编写一个单元测试。

So I want to inject a fake-fixed "now" date (making the test determine). 因此,我想注入一个假固定的“现在”日期(使测试确定)。

I have tried to inject a spy like this: 我试图注入这样的间谍:

private ImagesSorter setServerWithSpyImageSorter(User user, List imagesAsInsertionOrder, Date fakeNowDate) throws IOException {
        ImagesSorter imagesSorter = spy(new ImagesSorter());
        when(imagesSorter.sortImages(imagesAsInsertionOrder, user)).thenReturn(imagesSorter.sortImages(imagesAsInsertionOrder, user, fakeNowDate));
        //doReturn(imagesSorter.sortImages(imagesAsInsertionOrder, user, fakeNowDate)).when(imagesSorter).sortImages(imagesAsInsertionOrder, user);
        server = VenueServerImplBuilder.create().withImagesSorter(imagesSorter).build();
        server.init();
        return imagesSorter;
    }

but it doesn't work. 但这不起作用。

1) when I used doReturn(imagesSorter.sortIm.. it was eagerly evaluated. I didn't want that to happen. Can I avoid this? 1)当我使用doReturn(imagesSorter.sortIm..它进行了热切的评估。我不希望这种情况发生。我可以避免这种情况吗?

2) when I commented out the doReturn(.. and used when(imagesSorter.sor 2)当我注释掉doReturn(..并使用when(imagesSorter.sor

I got the following error: 我收到以下错误:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:



E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

how would you code what I want to do? 您将如何编码我要做什么?

This syntax doesn't work for spies: 此语法不适用于间谍:

when(imagesSorter.sortImages(imagesAsInsertionOrder, user)).thenReturn(imagesSorter.sortImages(imagesAsInsertionOrder, user, fakeNowDate));

You need to use this construct: 您需要使用以下构造:

doReturn(imagesSorter.sortImages(imagesAsInsertionOrder, user, fakeNowDate)).when(imagesSorter).sortImages(imagesAsInsertionOrder, user));

Here is relevant documentation (see section "Important gotcha on spying real objects!"): http://static.javadoc.io/org.mockito/mockito-core/2.8.47/org/mockito/Mockito.html#13 这是相关的文档(请参阅“监视真实对象的重要提示!”部分): http : //static.javadoc.io/org.mockito/mockito-core/2.8.47/org/mockito/Mockito.html#13

I don't think you need Mockito to create your mock here. 我认为您不需要Mockito在此处创建模拟。 Since ImageSorter is a concrete class, you can't make a real decorator, but you can make something like: 由于ImageSorter是一个具体的类,因此您不能创建真正的装饰器,但是可以执行以下操作:

public class FixedDateImageSorter extends ImagesSorter {

    final Date fixedDdate;

    FixedDateImageSorter(Date fixedDate) {
        this.fixedDdate = fixedDate;
    }

    public List sortImages(List s, User u) {
        return sortImages(s, u, fixedDdate);
    }
}

Then 然后

private ImagesSorter setServerWithSpyImageSorter(User user, List imagesAsInsertionOrder, Date fakeNowDate) throws IOException {
    ImagesSorter imagesSorter = new FixedDateImageSorter(fakeNowDate);
    server = VenueServerImplBuilder.create().withImagesSorter(imagesSorter).build();
    server.init();
    return imagesSorter;
}

If you really want to a Mockito spy, then as you said the doReturn is eagerly evaluated. 如果您真的想要Mockito间谍,那么正如您所说的, doReturn得到急切的评估。 So you need to use the doAnswer to lately evaluate the response: 因此,您需要使用doAnswer最近评估响应:

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doAnswer;

...

final Date fakeNowDate = new Date();
final ImagesSorter imagesSorter = spy(new ImagesSorter());

doAnswer(new Answer<List>() {
    public List answer(InvocationOnMock invocation) throws Throwable {
        // Get the actual arguments
        List arg1 = (List) invocation.getArguments()[0];
        User arg2 = (User) invocation.getArguments()[1];
        // Then call the 3-args method using fakeNowDate
        return imagesSorter.sortImages(arg1, arg2, fakeNowDate);
    }
}).when(imagesSorter).sortImages(any(List.class), any(User.class));

But i don't think it's the best approach. 但是我不认为这是最好的方法。

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

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