久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

模擬;使用列表調用驗證方法,忽略列表中元素的

Mockito; verify method was called with list, ignore order of elements in list(模擬;使用列表調用驗證方法,忽略列表中元素的順序)
本文介紹了模擬;使用列表調用驗證方法,忽略列表中元素的順序的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我有一個類 (ClassA) 可以獲取目錄中的文件.它掃描給定目錄以查找匹配正則表達式的文件.對于每個匹配的文件,它會將一個文件對象添加到列表中.處理完目錄后,會將文件列表傳遞給另一個類(ClassB)進行處理

I have a class (ClassA) that get the files in a directory. It scans the given directory for files matching a regex. For each matching file, it adds a File Object to a list. Once the directory is processed, it passes the List of Files to another Class (ClassB) for processing

我正在為 ClassA 編寫單元測試,所以我正在使用 Mockito 模擬 ClassB,并將其注入 ClassA.然后我想在不同的場景中驗證傳遞給 ClassB 的列表的內容(即我的模擬)

I am writing unit tests for ClassA, so am mocking ClassB using Mockito, and injecting it into ClassA. I then want to verify in different scenarios the contents of the list that is passed to ClassB (ie my mock)

我已將代碼剝離為以下內容

I've stripped back the code to the following

public class ClassA implements Runnable {

    private final ClassB classB;

    public ClassA(final ClassB classB) {
        this.classB = classB;
    }

    public List<File> getFilesFromDirectories() {
        final List<File> newFileList = new ArrayList<File>();
        //        ...
        return newFileList;
    }

    public void run() {
        final List<File> fileList = getFilesFromDirectories();

        if (fileList.isEmpty()) {
            //Log Message
        } else {
            classB.sendEvent(fileList);
        }
    }
}

測試類是這樣的

    @RunWith(MockitoJUnitRunner.class)
    public class AppTest {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Mock
    private ClassB mockClassB;

    private File testFileOne;

    private File testFileTwo;

    private File testFileThree;

    @Before
    public void setup() throws IOException {
        testFileOne = folder.newFile("testFileA.txt");
        testFileTwo = folder.newFile("testFileB.txt");
        testFileThree = folder.newFile("testFileC.txt");
    }

    @Test
    public void run_secondFileCollectorRun_shouldNotProcessSameFilesAgainBecauseofDotLastFile() throws Exception {
        final ClassA objUndertest = new ClassA(mockClassB);

        final List<File> expectedFileList = createSortedExpectedFileList(testFileOne, testFileTwo, testFileThree);
        objUndertest.run();

        verify(mockClassB).sendEvent(expectedFileList);
    }

    private List<File> createSortedExpectedFileList(final File... files) {
        final List<File> expectedFileList = new ArrayList<File>();
        for (final File file : files) {
            expectedFileList.add(file);
        }
        Collections.sort(expectedFileList);
        return expectedFileList;
    }
}

問題是這個測試在 Windows 上運行良好,但在 Linux 上失敗.原因是在windows上,ClassA列出文件的順序與expectedList相匹配,所以行

The problem is that this test works perfectly fine on windows, but fails on Linux. The reason being that on windows, the order that ClassA list the files matches the expectedList, so the line

verify(mockClassB).sendEvent(expectedFileList);

在 Windows 上會導致問題 expecetdFileList = {FileA, FileB, FileC},而在 Linux 上會是 {FileC, FileB, FileA},因此驗證失敗.

is causing the problem expecetdFileList = {FileA, FileB, FileC} on Windows, whereas on Linux it will be {FileC, FileB, FileA}, so the verify fails.

問題是,我如何在 Mockito 中解決這個問題.有沒有辦法說,我希望這個方法被這個參數調用,但是我不關心列表內容的順序.

The question is, how do I get around this in Mockito. Is there any way of saying, I expect this method to be be called with this parameter, but I don't care about the order of the contents of the list.

我確實有一個解決方案,我只是不喜歡它,我寧愿有一個更干凈、更易于閱讀的解決方案.

I do have a solution, I just don't like it, I would rather have a cleaner, easier to read solution.

我可以使用 ArgumentCaptor 獲取傳遞給模擬的實際值,然后對其進行排序,并將其與我的預期值進行比較.

I can use an ArgumentCaptor to get the actual value passed into the mock, then can sort it, and compare it to my expected values.

    final ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
    verify(mockClassB).method(argument.capture());
    Collections.sort(expected);
    final List<String> value = argument.getValue();
    Collections.sort(value);
    assertEquals(expecetdFileList, value);

推薦答案

在另一個答案中指出,如果您不關心訂單,您可能最好更改界面,使其不關心訂單.

As noted in another answer, if you don't care about the order, you might do best to change the interface so it doesn't care about the order.

如果順序在代碼中很重要,但在特定測試中不重要,您可以像以前一樣使用 ArgumentCaptor.代碼有點混亂.

If order matters in the code but not in a specific test, you can use the ArgumentCaptor as you did. It clutters the code a bit.

如果這是您可能在多個測試中執行的操作,則最好使用適當的 Mockito Matchers 或 Hamcrest Matchers,或者自己動手制作(如果你找不到滿足需要的).hamcrest matcher 可能是最好的,因為它可以在 mockito 之外的其他上下文中使用.

If this is something you might do in multiple tests, you might do better to use appropriate Mockito Matchers or Hamcrest Matchers, or roll your own (if you don't find one that fills the need). A hamcrest matcher might be best as it can be used in other contexts besides mockito.

對于本示例,您可以按如下方式創建 hamcrest 匹配器:

For this example you could create a hamcrest matcher as follows:

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MyMatchers {
    public  static <T> Matcher<List<T>> sameAsSet(final List<T> expectedList) {
        return new BaseMatcher<List<T>>(){
            @Override
            public boolean matches(Object o) {
                List<T> actualList = Collections.EMPTY_LIST;
                try {
                    actualList = (List<T>) o;
                }
                catch (ClassCastException e) {
                    return false;
                }
                Set<T> expectedSet = new HashSet<T>(expectedList);
                Set<T> actualSet = new HashSet<T>(actualList);
                return actualSet.equals(expectedSet);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("should contain all and only elements of ").appendValue(expectedList);
            }
        };
    }
}

然后驗證碼變成:

verify(mockClassB).sendEvent(argThat(MyMatchers.sameAsSet(expectedFileList)));

如果您改為創建模擬匹配器,則不需要 argThat,它基本上將 hamcrest 匹配器包裝在模擬匹配器中.

If you instead created a mockito matcher, you wouldn't need the argThat, which basically wraps a hamcrest matcher in a mockito matcher.

這會將排序或轉換的邏輯移出您的測試并使其可重用.

This moves the logic of sorting or converting to set out of your test and makes it reusable.

這篇關于模擬;使用列表調用驗證方法,忽略列表中元素的順序的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How to mock super reference (on super class)?(如何模擬超級參考(在超級類上)?)
Java mock database connection(Java 模擬數據庫連接)
Mockito ClassCastException - A mock cannot be cast(Mockito ClassCastException - 無法投射模擬)
Set value to mocked object but get null(將值設置為模擬對象但獲取 null)
How to mock DriverManager.getConnection(...)?(如何模擬 DriverManager.getConnection(...)?)
Is it possible to create a mock object that implements multiple interfaces with EasyMock?(是否可以使用 EasyMock 創建一個實現多個接口的模擬對象?)
主站蜘蛛池模板: 欧美色成人 | av色噜噜| 国产视频第一页 | 一区欧美 | 国产高清毛片 | 69电影网 | 99re热精品视频国产免费 | 欧美性猛交| 中文字幕 在线观看 | 一区二区免费 | 国产一区二区三区在线看 | 第一av| 奇米四色影视 | 91精品国产91久久久久游泳池 | 欧美日韩久久 | 亚洲精品68久久久一区 | 亚洲精品视频免费看 | 国产精品爱久久久久久久 | 91人人看 | 男女视频免费 | 国产精品成av人在线视午夜片 | 久久久中文 | 99热国产精品 | 91精品www | 日韩中文在线 | 日日碰狠狠躁久久躁96avv | 亚洲福利一区二区 | a级黄色网 | 精品在线一区 | 欧美午夜在线 | 久久久久国产视频 | 国产免费福利在线 | 国产精品一区二区在线免费观看 | 天堂av免费观看 | 日韩av在线中文字幕 | 久久久99国产精品免费 | 精品国产一区二区三区av片 | 日本一区二区影视 | 欧美天堂 | 成人国产在线视频 | 蜜臀网 |