jUnit & Mockito - 模拟"when"触发验证



我在这里解释我的代码,但我的问题是这样。

我有一个模拟课:

@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);提供预期结果。

问题 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 阅读更多内容(。在您的情况下,有大量的模拟,这对于给定的测试方法来说是不需要的(甚至更多 - 您根本不想要任何交互(。这使得在发生错误时很难进行调试。

相关内容

  • 没有找到相关文章

最新更新