久久久久久久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在线播放 | 中文字幕一区二区三区乱码在线 | 国产1区| 国产成人精品a视频 | 国产91亚洲精品一区二区三区 | 狠狠操av | 美女国内精品自产拍在线播放 | 一区二区三区中文字幕 | 男女羞羞免费网站 | 亚州春色 | 日韩精品久久久 | 亚洲一二视频 | 草久久| 国产精品久久毛片av大全日韩 | 宅男伊人 | 国产在线视频一区 | 一本色道精品久久一区二区三区 | 美女黄色在线观看 | 成人网在线观看 | 一区二区精品电影 | 成人免费视频观看视频 | 国产高清免费视频 | 最新av在线网址 | 黄免费观看视频 | 午夜成人免费视频 | 性一爱一乱一交一视频 | 免费一级黄色录像 | 成人免费视频网站在线看 | 色姑娘综合网 | 国产免费又黄又爽又刺激蜜月al | 久热久草| 午夜久久久 | 国产精品一区二区不卡 | 天堂中文在线观看 | 色婷婷精品国产一区二区三区 | 日本精品视频一区二区 | 国产视频一二三区 | 超碰网址|