Mockito:Java - 未完成的存根检测
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37747535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito:Java - Unfinished stubbing detection
提问by L1ghtk3ira
I have been working with Mockito and have run into this error message:
我一直在使用 Mockito 并遇到此错误消息:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.rbc.rewards.catalogue.service.B2SServicesTest.getProductList_Success(B2SServ icesTest.java:52)
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!
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
I have read in two posts on Stack Overflow about this issue but they do not go into full detail. I believe it has something to do with nesting mocks inside a mocking(from what I read). However I do not see or fully understand by the small snippets people have posted.
我在 Stack Overflow 上读过两篇关于这个问题的帖子,但没有详细介绍。我相信这与在模拟中嵌套模拟有关(根据我的阅读)。但是,我没有看到或完全理解人们发布的小片段。
My test class is as followed (leaving out unnecessary code):
我的测试类如下(省略了不必要的代码):
// Mock: uses Java Reflection in order to create mock objects of each class
@Mock
private Scrapes scrapeS;
@Mock
private SsoS ssoS;
@Mock
private BScrape bScrape;
//@InjectMocks annotation is used to create and inject the mock object
@Mock
private BService bService;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
// Testing:
@Test
public void getProductList_Success() throws Exception{
when(BService.getProductList("cookie", "6753"))
.thenReturn(
scrapeS.scrapePost(new String(),
new String(),
new HashMap<>(),
new bService()));
}
Method I need to call:
我需要调用的方法:
public List<prodItem> getProdList(String raw_cookie, String catId) throws Exception {
String url = ssoSetting.getUrls().BProductList();
String post = "url" + catId +"url";
BScrape scraper = new BScrape ();
Map<String, String> postRequest = new HashMap();
postRequest.put("searchRequestParams", post);
return scrapeS.scrapePost(url, raw_cookie, postRequest, scraper);
}
I am also using resources from TutorialsPoint.
我也在使用来自TutorialsPoint 的资源。
It is happening within the @test method and I believe this mocking inside mocking is because I am using it wrong I am assuming.
它发生在@test 方法中,我相信这种在模拟中的模拟是因为我假设我使用它是错误的。
After Implementation from Answer (working):
从答案实施后(工作):
@Mock
private SSetting sSetting = new SSetting ();
// Mock: uses Java Reflection in order to create mock objects and is injected into InjectMocks
@Mock
private ProdItem productItem = new ProdItem ();
@Mock
private sService scrapeService = new sService ();
@Mock
private BScrape bScrape ;
//@InjectMocks annotation is used to create and inject the mock object
@InjectMocks
private BService bService = new BService ();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
// Testing:
@Test
public void getProductList_Success() throws Exception{
List<ProductItem> retList = new ArrayList<>();
retList.add(new ProductItem());
retList.add(new ProductItem());
//try{
when(b2SServices.getProductList("cookie", "6753")).thenCallRealMethod();
//test the add functionality
when(BService .getProdList("cookie", "6753")).thenReturn(retList);
}catch(Exception exception){
System.out.println(exception);
}
}
回答by user1121883
You are in the third case:
您处于第三种情况:
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
3:如果完成,您正在'thenReturn'指令之前存根内部另一个模拟的行为
This happens because thenReturn calls method from another mock scrapeS.scrapePost
It is hard to say exactly how to fix this because I would need more implementation details but try building the return object before when
and it shouldn't be the return from another mock. There is a good explanation here: https://stackoverflow.com/a/26319364/1121883
发生这种情况是因为 thenReturn 从另一个模拟调用方法scrapeS.scrapePost
很难确切地说如何解决这个问题,因为我需要更多的实现细节,但尝试之前构建返回对象when
,它不应该是另一个模拟的返回。这里有一个很好的解释:https: //stackoverflow.com/a/26319364/1121883
Here is a small example. You code is similar to play
test. In then return you should provide an object instead of the call on the mock like in fix
test.
这是一个小例子。您的代码类似于play
测试。然后返回时,您应该提供一个对象,而不是像fix
测试中那样在模拟上调用。
@Test
public void play(){
A a = mock(A.class);
B b = mock(B.class);
when(a.a("input")).thenReturn(b.b("input"));
}
@Test
public void fix(){
A a = mock(A.class);
B b = mock(B.class);
String returnString = "b";
when(a.a("input")).thenReturn(returnString);
}
static class A{
String a(String in){
return "a";
}
}
static class B{
String b(String in){
return "b";
}
}
Your code should be something like:
你的代码应该是这样的:
List<prodItem> retList = new ArrayList<>();
retList.add(new ProdItem());
retList.add(new ProdItem());
when(bService.getProductList("cookie", "6753")).thenReturn(retList);
回答by SpaceTrucker
The (a bit simplified) evaluation order of your code
代码的(有点简化)评估顺序
when(bService.getProductList("cookie", "6753"))
.thenReturn(
scrapeS.scrapePost(new String(),
new String(),
new HashMap<>(),
new bService()));
is first:
首先是:
bService.getProductList("cookie", "6753")
second
第二
when(/*...*/)
third
第三
scrapeS.scrapePost(new String(),
new String(),
new HashMap<>(),
new bService())
.
.
So while trying to mock bService
you use mock scrapeS
.
因此,在尝试模拟时,bService
您可以使用 mock scrapeS
。
Note that this doesn't make sense at all. Basically you are currently trying to give bService.getProductList
an implementation which should use scrapeS
. But bService
is a mock and therefore has no implementaion.
请注意,这完全没有意义。基本上,您目前正在尝试提供bService.getProductList
一个应该使用scrapeS
. 但是bService
是一个模拟,因此没有实现。
If you want that the invocations of bService
and scrapeS
return the same object then store that object into a local variable and use that local variable in the thenReturn
clause of both methods.
如果您希望调用bService
和scrapeS
返回同一对象,则将该对象存储到局部变量中,并在thenReturn
两种方法的子句中使用该局部变量。
Object returnValue = /*whatever the return value is*/
when(bService.getProductList("cookie", "6753")).thenReturn(returnValue);
when(scrapeS.scrapePost(new String(), new String(), new HashMap<>(), new bService())).thenReturn(returnValue);