日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

测试双重图案

發布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 测试双重图案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前段時間,我寫了一篇有關使用Test Double的后果的文章,但是與Test Double Patterns無關,僅是一個簡單的清單。 今天,我想對其進行更改,并解釋這些模式之間的差異。

正如我在提到的文章中寫道:

Test Double是允許我們控制被測單元之間依賴性的模式。 為了能夠在我們想要或/和/或驗證是否發生想要的行為時提供想要的行為。
因此,現在讓您想起了基礎知識時,我們可以轉到有趣的部分–讓我們看一下“測試雙重模式”。

虛擬對象

虛擬是TD(測試雙精度),當我們想要傳遞對象以填充參數列表時使用。 從未實際使用過。 這就是為什么它不總是被視為TD之一的原因-它不提供任何行為。

假設我們有發送報告的Sender類。 由于某些要求,我們需要將其包裝到另一個類中以提供有效的接口。 我們的課看起來像這樣:

public class ReportProcessor implements Processor {private Sender sender;public ReportProcessor(Sender sender) {this.sender = sender;}@Overridepublic void process(Report report) {sender.send(report);} }

現在,我們的測試是什么樣的? 我們需要驗證什么? 我們必須檢查報告是否傳遞給Sender實例的send()方法。 可以按照以下步驟完成:

public class DummyTest {@Testpublic void shouldSentReportWhileProcessing() {Sender sender = aMessageSender();ReportProcessor reportProcessor = aReportProcessor(sender);Report dummyReport = new Report();reportProcessor.process(dummyReport);then(sender).should().send(dummyReport);}private ReportProcessor aReportProcessor(Sender sender) {return new ReportProcessor(sender);}private Sender aMessageSender() {return spy(Sender.class);} }

如您所見,與我們的虛擬對象沒有任何交互。 僅創建報告并將其作為參數傳遞。 沒有行為,只有存在。

假物件

Fake Object只是測試類所依賴的對象的一種更簡單,更輕量的實現。 它提供了預期的功能。

在決定時要記住的重要事項是使其盡可能簡單。 任何其他邏輯都可能對測試的脆弱性和準確性產生重大影響。

假設我們有一個帶create()方法的ReportService,它的責任是僅在尚未創建Report的情況下創建一個Report。 為簡單起見,我們可以假設標題標識一個對象–我們不能有兩個標題相同的報表:

public class ReportService {private ReportRepository reportRepository;public ReportService(ReportRepository reportRepository) {this.reportRepository = reportRepository;}public void create(Title title, Content content) {if (!reportRepository.existsWithTitle(title)) {Report report = new Report(title, content);reportRepository.add(report);}} }

我們可以通過多種方式測試此代碼,但我們將決定使用Fake Object:

class FakeReportRepository implements ReportRepository {private Map<Title, Report> reports = new HashMap<>();@Overridepublic void add(Report report) {reports.put(report.title(), report);}@Overridepublic boolean existsWithTitle(Title title) {return reports.containsKey(title);}@Overridepublic int countAll() {return reports.size();}@Overridepublic Report findByTitle(Title title) {return reports.get(title);} }

我們的測試將如下所示:

public class FakeTest {@Testpublic void shouldNotCreateTheSameReportTwice() {FakeReportRepository reportRepository = new FakeReportRepository();ReportService reportService = aReportService(reportRepository);reportService.create(DUMMY_TITLE, DUMMY_CONTENT);reportService.create(DUMMY_TITLE, DUMMY_CONTENT);Report createdReport = reportRepository.findByTitle(DUMMY_TITLE);assertThat(createdReport.title()).isSameAs(DUMMY_TITLE);assertThat(createdReport.content()).isSameAs(DUMMY_CONTENT);assertThat(reportRepository.countAll()).isEqualTo(1);}private ReportService aReportService(ReportRepository reportRepository) {return new ReportService(reportRepository);} }

存根對象

我們在對方法輸出感興趣的情況下使用Stub Object,以確保每次調用它時結果都將完全符合我們的期望。

通常,我們不會在測試中檢查是否調用了Stub,因為我們會通過其他斷言知道它。

在此示例中,我們將查看一個ReportFactory,該工廠將創建具有創建日期的報表。 為了可測試性,我們使用了依賴注入來注入DateProvider:

public class ReportFactory {private DateProvider dateProvider;public ReportFactory(DateProvider dateProvider) {this.dateProvider = dateProvider;}public Report crete(Title title, Content content) {return new Report(title, content, dateProvider.date());} }

它允許我們在測試中使用Stub:

public class StubTest {@Testpublic void shouldCreateReportWithCreationDate() {Date dummyTodayDate = new Date();DateProvider dateProvider = mock(DateProvider.class);stub(dateProvider.date()).toReturn(dummyTodayDate);ReportFactory reportFactory = new ReportFactory(dateProvider);Report report = reportFactory.crete(DUMMY_TITLE, DUMMY_CONTENT);assertThat(report.creationDate()).isSameAs(dummyTodayDate);} }

如您所見,我們僅對調用Stub的結果感興趣。

間諜對象

與Stub對象相反,當我們對間諜方法的輸入感興趣時,我們將使用Spies。 我們正在檢查它是否被調用。 我們可以檢查它被調用了多少次。

我們也可以將實際的應用程序對象用作間諜。 無需創建任何其他類。

讓我們從第一段回到ReportProcessor:

public class ReportProcessor implements Processor {// code@Overridepublic void process(Report report) {sender.send(report);} }

可能您已經注意到我們在那里使用了Spy,但讓我們再次看一下測試:

public class SpyTest {@Testpublic void shouldSentReportWhileProcessing() {Sender sender = spy(Sender.class);ReportProcessor reportProcessor = aReportProcessor(sender);reportProcessor.process(DUMMY_REPORT);then(sender).should().send(DUMMY_REPORT);}private ReportProcessor aReportProcessor(Sender sender) {return new ReportProcessor(sender);} }

我們要檢查對象是否以正確的方式包裝,并將參數傳遞給其(包裝的對象)方法調用。 這就是為什么我們在這里使用Spy的原因。

模擬對象

模擬對象通常被描述為Stub和Spy的組合。 我們指定期望接收的輸入,并在此基礎上返回正確的結果。

如果這是我們期望的,則調用模擬對象也可能導致拋出異常。

好的,讓我們再次看一下ReportService:

public class ReportService {//codepublic void create(Title title, Content content) {if (!reportRepository.existsWithTitle(title)) {Report report = new Report(title, content);reportRepository.add(report);}} }

現在,我們將使用模擬對象代替偽對象:

@RunWith(MockitoJUnitRunner.class) public class MockTest {@Mock private ReportRepository reportRepository;@InjectMocks private ReportService reportService;@Testpublic void shouldCreateReportIfDoesNotExist() {given(reportRepository.existsWithTitle(DUMMY_TITLE)).willReturn(false);reportService.create(DUMMY_TITLE, DUMMY_CONTENT);then(reportRepository).should().add(anyReport());}@Testpublic void shouldNotCreateReportIfDoesNotExist() {given(reportRepository.existsWithTitle(DUMMY_TITLE)).willReturn(true);reportService.create(DUMMY_TITLE, DUMMY_CONTENT);then(reportRepository).should(never()).add(anyReport());}private Report anyReport() {return any(Report.class);} }

為了澄清一切,我們的模擬對象是ReportRepository.existsWithTitle()方法。 如您所見,在第一個測試中,我們說如果調用帶有DUMMY_OBJECT參數的方法,它將返回true。 在第二個測試中,我們檢查相反的情況。

我們在兩個測試中的最后一個斷言(then()。should())是另一個TD模式。 你能認出哪一個嗎?

最后一句話

這就是我今天要說的有關測試雙重模式的全部內容。 我鼓勵您有意使用它們,不要盲目遵循在可能的情況下添加@Mock注釋的習慣。

我還邀請您閱讀有關使用Test Double的后果的文章,以了解使用TD模式時可能遇到的問題以及如何識別和解決此類問題。

如果您想進一步加深對這些模式的了解,那么會有一個很棒的頁面可以幫助您做到這一點: xUnit模式:Test Double 。

祝您測試順利! 使它們可讀且有價值。

如果您對“測試雙模式”有任何想法或疑問,請在評論中分享。

翻譯自: https://www.javacodegeeks.com/2015/09/test-double-patterns.html

總結

以上是生活随笔為你收集整理的测试双重图案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。