簡體   English   中英

jUnit&Mockito-模擬“何時”觸發驗證

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM