簡體   English   中英

用許多模擬對象創建測試?

[英]Creating tests with many mock objects?

我對是否應該創建包含許多模擬對象的測試感到懷疑。

我最近讀了我什么時候應該嘲笑? 我感到困惑。

讓我們看一下我擁有的一種方法(只是為了說明問題)

@Override
protected void validate() throws WTException {
    Either<ImportError, RootFinderResult> rootPart = getDataValidator().getRootPart();
    if (rootPart.isLeft()) {
        addValidationMessage(ROOT_PART_NOT_FOUND);
    } else if (rootPart.isRight()) {
        getObjectsToValidate().forEach(Lambda.uncheckedBiConsumer((part, epmDocuments) -> {
            LocalizableMessage rootRevision = getRevision(part);

            Optional<EPMDocument> wrongRevisionEPM = epmDocuments.stream()
                    .filter(epmDocument -> !isSameRevision(rootRevision, epmDocument))
                    .findAny();

            wrongRevisionEPM.ifPresent(epmDocument -> addValidationMessage("blabla"));
        }));
    }
}

以下所有方法都需要與服務器建立連接才能起作用,否則它們將引發錯誤

getDataValidator().getRootPart();
getRevision(part)
!isSameRevision(rootRevision, epmDocument))

另外,我無法創建零件或epm文檔的“真實”對象。 這也需要與服務器建立連接。


所以在這一點上,我真正要測試的實際上是這部分代碼的邏輯

    Optional<EPMDocument> wrongRevisionEPM = epmDocuments.stream()
            .filter(epmDocument -> !isSameRevision(rootRevision, epmDocument))
            .findAny();

    wrongRevisionEPM.ifPresent(epmDocument -> addValidationMessage("blabla"));

但是要測試它,我需要模擬很多對象

@Spy
@InjectMocks
private SameRevision sameRevision;
@Mock
private WTPartRelatedObjectDataValidator wTPartRelatedObjectDataValidator;
@Mock
private ValidationEntry validationEntry;
@Mock
private WTPart rootPart1, rootPart2;
@Mock
private EPMDocument epmDocument1, epmDocument2, epmDocument3;
@Mock
private Either<ImportError, RootFinderResult> rootPart;
@Mock
private LocalizableMessage rootPartRevisionOne, rootPartRevisionTwo;

所以最后我可以測試邏輯:

@Test
@DisplayName("Should contain error message when part -> epms revisions are not the same")
void shoulHaveErrorMessagesWhenDifferentRevisions() throws Exception {
    doReturn(getMockObjectsToValidate()).when(sameRevision).getObjectsToValidate();

    doReturn(rootPart).when(liebherrWTPartRelatedObjectDataValidator).getRootPart();
    doReturn(false).when(rootPart).isLeft();
    doReturn(true).when(rootPart).isRight();

    doReturn(rootPartRevisionOne).when(sameRevision).getRevision(rootPart1);
    doReturn(rootPartRevisionTwo).when(sameRevision).getRevision(rootPart2);

    doReturn(true).when(sameRevision).isSameRevision(rootPartRevisionOne, epmDocument1);
    doReturn(false).when(sameRevision).isSameRevision(rootPartRevisionOne, epmDocument2);
    doReturn(true).when(sameRevision).isSameRevision(rootPartRevisionTwo, epmDocument3);

    validationEntry = sameRevision.call();

    assertEquals(1, validationEntry.getValidationMessageSet().size());
}

哪里

    doReturn(rootPart).when(liebherrWTPartRelatedObjectDataValidator).getRootPart();
    doReturn(false).when(rootPart).isLeft();
    doReturn(true).when(rootPart).isRight();

    doReturn(rootPartRevisionOne).when(sameRevision).getRevision(rootPart1);
    doReturn(rootPartRevisionTwo).when(sameRevision).getRevision(rootPart2);

可以移到@BeforeEach。


最后,我進行了測試,它可以正常工作。 它驗證了我想要驗證的內容,但是為了達到這一點,我不得不付出很多努力才能通過需要與服務器交互的整個API。

你們怎么看,創建這樣的測試值得嗎? 我想這是一個開放的話題,“因為許多嘗試進入“測試世界”的新手都會遇到類似的問題,因此,請不要因為基於觀點的判斷而關閉該話題,並提供您對該話題的反饋。

您應該模擬將要測試的類所依賴的其他依賴關系,並設置所需的行為。 這需要完成以測試您的方法是否孤立,並且不依賴於thrirdparty類。您可以編寫私有的void方法,該方法可以包含模擬行為,並在測試中使用它們;在@BeforeEach帶注釋的方法中,您可以模擬在所有測試中都相同的行為或在所有測試中模擬相同的模擬行為

在無效的方法中,您可以擁有一些間諜對象,如果像Mockito.verify()這樣調用它們,則可以對其進行仿制。

你是對的。 模擬所有這些依賴關系是一項巨大的努力。 讓我談談一些可能使事情變得更清楚的點:

  • 像對待投資一樣對待編寫測試:因此,是的,有時編寫測試要比編寫實際代碼花費更多的精力。 但是,稍后引入錯誤時,您將感激不盡,並且測試可以抓住它。 擁有良好的測試可以使您有信心在修改代碼時不會破壞任何內容,如果這樣做,則測試會找到問題所在。 隨着時間的流逝,它會得到回報。

  • 讓您的考試集中在特定的課程上。 模擬其余部分:當模擬除被測類之外的所有內容時,可以確定發生問題時,該問題來自被測類,而不是其依賴項之一。 這使故障排除變得更加容易。

  • 編寫新代碼時要考慮可測試性:有時候,不可避免地要編寫復雜的代碼,很難測試。 但是,通常可以通過將所需的依賴項數量保持在最低限度並編寫可測試的代碼來避免這種情況。 例如,如果一個方法需要5或6個以上的依賴關系來完成其工作,則該方法可能做得太多,可能會分解。 可以在類級別,模塊等上說同樣的話。

是的,當您必須模擬這么多東西時,是相當多的投資時間。 我認為,如果您在測試某件產品時增加了一些價值,那值得進行測試,那么問題當然可能是您要花費多少時間。

在您的特定情況下,我將在不同的“層”上進行測試。

例如,方法:getDataValidator()。getRootPart(); getRevision(part)!isSameRevision(rootRevision,epmDocument))

可以對它們進行獨立測試,並在您的情況下僅模擬其結果,這意味着您實際上並不關心那里的參數,您只關心在有特定返回值的情況下會發生什么。

因此,您可以在一層上真正地測試該功能,而在下一層上,您只需模擬所需的結果即可測試另一功能。

我希望現在更清楚...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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