[英]jUnit & Mockito - Mocked “when” triggers verification
我在这里解释我的代码,但是问题是这样的。
我有一个模拟课:
@Mock
private MyClass myInstance;
在我的代码中,我有一个对myInstance
的调用,该调用将在执行过程中进行,因此将其存入setUp方法中:
@Before
public void setUp() {
Mockito.when(myInstance.doSomething("Input String")).thenReutrn("Output String");
}
在执行过程中可能会发生这种情况,并且在测试中我可以验证这一点,但是有一个测试不会发生我已打断的交互(永远不会做某事),因此我在这些条件下进行了测试,最初的想法是验证此交互不会发生:
Mockito.verify(myInstance, times(0)).doSomething("Input String");
要么
Mockito.verifyZeroInteractions(myInstance);
当我运行此测试时,这些验证语句失败,并显示一条消息(再次解释),没有预期的交互作用-指向这些验证语句,但是找到了交互作用。 该消息指向设置方法中的存根。
问题1:测试中的条件意味着myInstance.doSomething("Input String");
在执行过程中永远不会调用它,并且给定(至少在我看来)验证是为了验证执行过程中发生了什么或没有发生什么,为什么存根的设置会对此产生干扰?
一种快速的解决方案是将该存根移出setUp方法,并移至该交互有效的一个测试中,这将给我Mockito.verifyZeroInteractions(myInstance);
的预期结果Mockito.verifyZeroInteractions(myInstance);
在另一个测试中。
问题2:但是,如果我引入第三个也需要此存根的测试该怎么办……我宁愿不要在此新测试中重复设置存根的代码,而希望在setUp中避免它复制。 有没有办法做到这一点,仍然有Mockito.verifyZeroInteractions(myInstance);
按预期工作?
希望我在这里对自己的解释足够好:)
干杯
隶
编辑:要求的代码
被测课程
public class GnerateChangeCountryList extends TagSupport implements ChangeControlConstants {
private static final long serialVersionUID = -6161465612237982393L;
private static final Logger LOGGER = LoggerFactory.getLogger(GnerateChangeCountryList.class);
private Node changeControlNode;
/**
* {@inheritDoc}
*/
@Override
public int doStartTag() throws JspException {
try {
NodeIterator countriesIterator = changeControlNode.getNode(COUNTRY_NODE_NAME).getNodes();
System.out.println("!!!!");
List<CountryChangeBean> countryList = new ArrayList<CountryChangeBean>();
while (countriesIterator.hasNext()) {
System.out.println("xxxxx");
Node country = countriesIterator.nextNode();
// Get the properties from the nodes
String countryLanguageCode = country.getProperty("languageCountryCode").getString();
String countryChangeStatus = country.getProperty("chgstatus").getString();
String countryName = country.getProperty("countryName").getString();
String countryUserName = country.getProperty("userName").getString();
String countryUserComment = country.getProperty("userComment").getString();
// Need to convert the last modified date to simple date format
// so it is handled differently
Property lastModifiedProperty = country.getProperty("cq:lastModified");
Calendar lastModifiedValue = lastModifiedProperty.getDate();
SimpleDateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
String formattedLastModifiedDate = df.format(lastModifiedValue.getTime());
String showSiteValue = country.getProperty("showSite").getString();
String showSiteString = "";
if (!showSiteValue.equals("yes")) {
showSiteString = "Not Shown";
}
countryList.add(new CountryChangeBean(countryLanguageCode, countryChangeStatus, countryName,
countryUserName, countryUserComment, showSiteString, formattedLastModifiedDate));
pageContext.setAttribute("countryList", countryList);
}
} catch (PathNotFoundException e) {
System.out.println("#####");
LOGGER.error("Error looking up the .\"{}\" node for the change. Exception = {}", COUNTRY_NODE_NAME, e);
} catch (RepositoryException e) {
LOGGER.error("Repository exception when trying to retrieve data. Exception = {}", e);
}
return SKIP_BODY;
}
/**
* Sets the node representing the change in question.
* @param changeControlNode the change node
*/
public void setChangeControlNode(Node changeControlNode) {
this.changeControlNode = changeControlNode;
}
}
测试类(我删除了其他测试以尽量简化)
从本质上来说,我期望的是,由于我的测试强制执行PathNotFoundException,因此对我存根的country.getProperty()
的调用永远不会发生,并且调试它们不会的代码,但是可惜验证失败:
@RunWith(MockitoJUnitRunner.class)
public class TestGnerateChangeCountryList implements ChangeControlConstants {
private static final String LANGUAGE_COUNTRY_CODE_PROPERTY = "languageCountryCode";
private static final String LANGUAGE_COUNTRY_CODE_VALUE = "en_gb";
private static final String CHANGE_STATUS_PROPERTY = "chgstatus";
private static final String CHANGE_STATUS_VALUE = "outstanding";
private static final String COUNTRY_NAME_PROPERTY = "countryName";
private static final String COUNTRY_NAME_VALUE = "UK";
private static final String USER_NAME_PROPERTY = "userName";
private static final String USER_NAME_VALUE = "someone";
private static final String USER_COMMENT_PROPERTY = "userComment";
private static final String USER_COMMENT_VALUE = "this is a comment";
private static final String LAST_MODIFIED_PROPERTY = "cq:lastModified";
private static final String SHOW_SITE_PROPERTY = "showSite";
private static final String SHOW_SITE_VALUE = "yes";
private static final String NOT_SHOW_SITE_VALUE = "no";
@Mock
private PageContext pageContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Node changeControlNode;
@Mock
private NodeIterator countriesIterator;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Node country;
@Mock
private Property lastModifiedProperty;
private GnerateChangeCountryList classUnderTest;
private Calendar lastModifiedValue;
@Before
public void setUp() throws PathNotFoundException, RepositoryException {
lastModifiedValue = new GregorianCalendar();
lastModifiedValue.setTime(new Date());
classUnderTest = new GnerateChangeCountryList();
classUnderTest.setPageContext(pageContext);
classUnderTest.setChangeControlNode(changeControlNode);
Mockito.when(countriesIterator.hasNext()).thenReturn(true, false);
Mockito.when(countriesIterator.nextNode()).thenReturn(country);
Mockito.when(country.getProperty(LANGUAGE_COUNTRY_CODE_PROPERTY).getString()).thenReturn(LANGUAGE_COUNTRY_CODE_VALUE);
Mockito.when(country.getProperty(CHANGE_STATUS_PROPERTY).getString()).thenReturn(CHANGE_STATUS_VALUE);
Mockito.when(country.getProperty(COUNTRY_NAME_PROPERTY).getString()).thenReturn(COUNTRY_NAME_VALUE);
Mockito.when(country.getProperty(USER_NAME_PROPERTY).getString()).thenReturn(USER_NAME_VALUE);
Mockito.when(country.getProperty(USER_COMMENT_PROPERTY).getString()).thenReturn(USER_COMMENT_VALUE);
Mockito.when(country.getProperty(LAST_MODIFIED_PROPERTY)).thenReturn(lastModifiedProperty);
Mockito.when(lastModifiedProperty.getDate()).thenReturn(lastModifiedValue);
}
/**
* Test when the countries node does not exist
*
*/
@Test
public void testWhenNoCountriesNodeFound() throws PathNotFoundException, RepositoryException, JspException {
Mockito.when(changeControlNode.getNode(COUNTRY_NODE_NAME)).thenThrow(new PathNotFoundException());
classUnderTest.setChangeControlNode(changeControlNode);
int result = classUnderTest.doStartTag();
Assert.assertEquals(TagSupport.SKIP_BODY, result);
Mockito.verifyZeroInteractions(country);
//Mockito.verify(country, Mockito.never()).getProperty(Mockito.anyString());
//Mockito.verify(pageContext, Mockito.times(0)).setAttribute(Mockito.anyString(), Mockito.any(List.class));
}
}
我没有适合您的解决方案,只有一点提示:您的测试方法应具有尽可能小的固定性(有关更多信息,请参见http://xunitpatterns.com/Minimal%20Fixture.html )。 在您的情况下,存在大量的模拟,这对于给定的测试方法是不需要的(甚至更多-您根本不需要任何交互)。 发生错误时,很难调试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.