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

模擬;使用列表調(diào)用驗證方法,忽略列表中元素的

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

問題描述

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

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 的列表的內(nèi)容(即我的模擬)

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)

我已將代碼剝離為以下內(nèi)容

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 上運(yùn)行良好,但在 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 上會導(dǎo)致問題 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 中解決這個問題.有沒有辦法說,我希望這個方法被這個參數(shù)調(diào)用,但是我不關(guān)心列表內(nèi)容的順序.

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.

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

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

我可以使用 ArgumentCaptor 獲取傳遞給模擬的實(shí)際值,然后對其進(jìn)行排序,并將其與我的預(yù)期值進(jìn)行比較.

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);

推薦答案

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

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.代碼有點(diǎn)混亂.

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.

如果這是您可能在多個測試中執(zhí)行的操作,則最好使用適當(dāng)?shù)?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.

對于本示例,您可以按如下方式創(chuàng)建 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)));

如果您改為創(chuàng)建模擬匹配器,則不需要 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.

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

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

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

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

相關(guān)文檔推薦

How to mock super reference (on super class)?(如何模擬超級參考(在超級類上)?)
Java mock database connection(Java 模擬數(shù)據(jù)庫連接)
Mockito ClassCastException - A mock cannot be cast(Mockito ClassCastException - 無法投射模擬)
Set value to mocked object but get null(將值設(shè)置為模擬對象但獲取 null)
How to mock DriverManager.getConnection(...)?(如何模擬 DriverManager.getConnection(...)?)
Is it possible to create a mock object that implements multiple interfaces with EasyMock?(是否可以使用 EasyMock 創(chuàng)建一個實(shí)現(xiàn)多個接口的模擬對象?)
主站蜘蛛池模板: 福利精品 | 亚洲国产精品99久久久久久久久 | 国产精品一区二区av | 欧美日韩久久精品 | 亚洲精品视频在线 | 欧美精品在线播放 | 午夜一级做a爰片久久毛片 精品综合 | 91精品国产综合久久久动漫日韩 | 日本欧美在线视频 | 久久人人网 | 欧美成人a | 久久精品一级 | 一区二区三区欧美 | 欧美中文一区 | 99国产精品久久久久久久 | 国产男女视频 | 成人免费观看视频 | 国产精品美女久久久久 | 亚洲一区精品在线 | 欧美性网 | 在线视频一区二区 | 亚洲高清免费观看 | 在线a视频 | 欧美日韩综合一区 | 日本精品国产 | 亚洲精品国产第一综合99久久 | 五月婷六月丁香 | 中文字幕一区二区三区不卡 | 九九免费| av男人的天堂av | 国产一区二区久久 | 色综合久久伊人 | 欧美国产在线一区 | 亚洲视频欧美视频 | 精品国产一区二区三区久久 | 野狼在线社区2017入口 | 国产一区二区欧美 | 久久久久亚洲 | 欧美日韩一 | 久久这里只有精品首页 | 免费黄色a视频 |