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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用模拟的单元测试–测试技术5

發(fā)布時(shí)間:2023/12/3 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用模拟的单元测试–测试技术5 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
我的最后一個(gè)博客是有關(guān)測(cè)試代碼方法的一系列博客中的第四篇,演示了如何創(chuàng)建使用存根對(duì)象隔離測(cè)試對(duì)象的單元測(cè)試。 今天的博客探討了有時(shí)被視為對(duì)立的技術(shù):使用模擬對(duì)象進(jìn)行單元測(cè)試。 同樣,我使用了從數(shù)據(jù)庫檢索地址的簡(jiǎn)單方案:

…并測(cè)試AddressService類:

@Component public class AddressService {private static final Logger logger = LoggerFactory.getLogger(AddressService.class);private AddressDao addressDao;/*** Given an id, retrieve an address. Apply phony business rules.* * @param id* The id of the address object.*/public Address findAddress(int id) {logger.info("In Address Service with id: " + id);Address address = addressDao.findAddress(id);address = businessMethod(address);logger.info("Leaving Address Service with id: " + id);return address;}private Address businessMethod(Address address) {logger.info("in business method");// Apply the Special Case Pattern (See MartinFowler.com)if (isNull(address)) {address = Address.INVALID_ADDRESS;}// Do some jiggery-pokery here....return address;}private boolean isNull(Object obj) {return obj == null;}@Autowired@Qualifier("addressDao")void setAddressDao(AddressDao addressDao) {this.addressDao = addressDao;} }

…通過將他的數(shù)據(jù)訪問對(duì)象替換為模擬對(duì)象。

在繼續(xù)之前,最好定義一個(gè)模擬對(duì)象的確切含義以及它與存根的不同之處。 如果您閱讀了我的上一篇博客,您會(huì)記得我讓Martin Fowler將存根對(duì)象定義為:

“存根提供對(duì)測(cè)試過程中進(jìn)行的呼叫的固定答復(fù),通常通常根本不響應(yīng)測(cè)試中編程的內(nèi)容。”

……摘自他的論文《 Mocks Are n't Stubs》 。

那么,模擬對(duì)象與存根有何不同? 當(dāng)您聽到人們談?wù)撃M對(duì)象時(shí),他們經(jīng)常提到他們?cè)诔靶?行為或嘲笑 角色 ,但這意味著什么? 答案在于單元測(cè)試和模擬對(duì)象共同測(cè)試對(duì)象的方式。 模擬對(duì)象場(chǎng)景如下所示:

  • 測(cè)試中定義了一個(gè)模擬對(duì)象。
  • 模擬對(duì)象被注入到您的測(cè)試對(duì)象中
  • 該測(cè)試指定將調(diào)用模擬對(duì)象上的哪些方法,以及參數(shù)和返回值。 這就是所謂的“ 設(shè)定期望 ”。
  • 然后運(yùn)行測(cè)試。
  • 然后,測(cè)試將要求模擬程序驗(yàn)證步驟3中指定的所有方法調(diào)用均已正確調(diào)用。 如果是,則測(cè)試通過。 如果不是,那么測(cè)試將失敗。
  • 因此,模擬行為或模擬角色實(shí)際上意味著檢查被測(cè)對(duì)象是否正確調(diào)用了模擬對(duì)象上的方法,如果沒有,則使測(cè)試失敗。 因此,您是在斷言方法調(diào)用的正確性和通過代碼的執(zhí)行路徑,而不是在常規(guī)單元測(cè)試的情況下斷言被測(cè)試方法的返回值。

    盡管有幾種專業(yè)的模擬框架,但在本例中,我首先決定產(chǎn)生自己的AddressDao模擬,它可以滿足上述要求。 畢竟,這有多難?

    public class HomeMadeMockDao implements AddressDao {/** The return value for the findAddress method */private Address expectedReturn;/** The expected arg value for the findAddress method */private int expectedId;/** The actual arg value passed in when the test runs */private int actualId;/** used to verify that the findAddress method has been called */private boolean called;/*** Set and expectation: the return value for the findAddress method*/public void setExpectationReturnValue(Address expectedReturn) {this.expectedReturn = expectedReturn;}public void setExpectationInputArg(int expectedId) {this.expectedId = expectedId;}/*** Verify that the expectations have been met*/public void verify() {assertTrue(called);assertEquals("Invalid arg. Expected: " + expectedId + " actual: " + expectedId, expectedId, actualId);}/*** The mock method - this is what we're mocking.* * @see com.captaindebug.address.AddressDao#findAddress(int)*/@Overridepublic Address findAddress(int id) {called = true;actualId = id;return expectedReturn;} }

    支持此模擬的單元測(cè)試代碼為:

    public class MockingAddressServiceWithHomeMadeMockTest {/** The object to test */private AddressService instance;/*** We've written a mock,,,*/private HomeMadeMockDao mockDao;@Beforepublic void setUp() throws Exception {/* Create the object to test and the mock */instance = new AddressService();mockDao = new HomeMadeMockDao();/* Inject the mock dependency */instance.setAddressDao(mockDao);}/*** Test method for* {@link com.captaindebug.address.AddressService#findAddress(int)}.*/@Testpublic void testFindAddressWithEasyMock() {/* Setup the test data - stuff that's specific to this test */final int id = 1;Address expectedAddress = new Address(id, "15 My Street", "My Town", "POSTCODE", "My Country");/* Set the Mock Expectations */mockDao.setExpectationInputArg(id);mockDao.setExpectationReturnValue(expectedAddress);/* Run the test */instance.findAddress(id);/* Verify that the mock's expectations were met */mockDao.verify();} }

    好的,盡管這演示了使用模擬對(duì)象執(zhí)行單元測(cè)試所需的步驟,但它相當(dāng)粗糙且準(zhǔn)備就緒,并且非常針對(duì)AddressDao / AddressService場(chǎng)景。 為了證明它已經(jīng)做得更好,下面的示例使用easyMock作為模擬框架。 在這種更專業(yè)的情況下,單元測(cè)試代碼為:

    @RunWith(UnitilsJUnit4TestClassRunner.class) public class MockingAddressServiceWithEasyMockTest {/** The object to test */private AddressService instance;/*** EasyMock creates the mock object*/@Mockprivate AddressDao mockDao;/*** @throws java.lang.Exception*/@Beforepublic void setUp() throws Exception {/* Create the object to test */instance = new AddressService();}/*** Test method for* {@link com.captaindebug.address.AddressService#findAddress(int)}.*/@Testpublic void testFindAddressWithEasyMock() {/* Inject the mock dependency */instance.setAddressDao(mockDao);/* Setup the test data - stuff that's specific to this test */final int id = 1;Address expectedAddress = new Address(id, "15 My Street", "My Town", "POSTCODE", "My Country");/* Set the expectations */expect(mockDao.findAddress(id)).andReturn(expectedAddress);replay();/* Run the test */instance.findAddress(id);/* Verify that the mock's expectations were met */verify();} }

    …我希望您會(huì)同意,這比我快速嘗試編寫模擬游戲更具進(jìn)步性。

    使用模擬對(duì)象的主要批評(píng)是它們將單元測(cè)試代碼與生產(chǎn)代碼的實(shí)現(xiàn)緊密耦合。 這是因?yàn)樵O(shè)置期望值的代碼緊密跟蹤生產(chǎn)代碼的執(zhí)行路徑。 這意味著即使該類仍履行其接口協(xié)定,后續(xù)對(duì)生產(chǎn)代碼的重構(gòu)也可能破壞大量測(cè)試。 這引起了這樣的斷言,即模擬測(cè)試相當(dāng)脆弱,并且您將花費(fèi)不必要的時(shí)間修復(fù)它們,根據(jù)我的經(jīng)驗(yàn),盡管我使用了“非嚴(yán)格”模擬,但這種模擬并不關(guān)心方法的順序,盡管我同意期望被稱為,在一定程度上減輕了問題。

    另一方面,一旦您知道如何使用諸如easyMock之類的框架,就可以非常快速有效地完成將您的對(duì)象隔離的單元測(cè)試。

    在自我批評(píng)該示例代碼時(shí),我想指出的是,我認(rèn)為在這種情況下使用模擬對(duì)象是過大的,此外,您還可以輕易地認(rèn)為我將模擬作為存根使用。

    幾年前,當(dāng)我第一次遇到easyMock時(shí),我在各處使用了模擬,但是最近我開始更喜歡手動(dòng)為應(yīng)用程序邊界類(例如DAO)和僅返回?cái)?shù)據(jù)的對(duì)象編寫存根。 這是因?yàn)榛诖娓臏y(cè)試可以說比基于模擬的測(cè)試要脆弱得多,尤其是當(dāng)您需要訪問數(shù)據(jù)時(shí)。

    為什么要使用模擬? 擅長(zhǎng)測(cè)試使用“ 告訴不要詢問 ”技術(shù)編寫的應(yīng)用程序,以驗(yàn)證是否調(diào)用了具有無效返回值的方法。

    參考: Captain Debug博客上來自JCG合作伙伴 使用Mocks進(jìn)行單元測(cè)試-測(cè)試技術(shù)5

    相關(guān)文章 :

    • 測(cè)試技巧–不編寫測(cè)試
    • 端到端測(cè)試的濫用–測(cè)試技術(shù)2
    • 您應(yīng)該對(duì)什么進(jìn)行單元測(cè)試? –測(cè)試技術(shù)3
    • 常規(guī)單元測(cè)試和存根–測(cè)??試技術(shù)4
    • 為舊版代碼創(chuàng)建存根–測(cè)試技術(shù)6
    • 有關(guān)為舊版代碼創(chuàng)建存根的更多信息–測(cè)試技術(shù)7
    • 為什么要編寫單元測(cè)試–測(cè)試技巧8
    • 一些定義–測(cè)試技術(shù)9
    • 使用FindBugs產(chǎn)生更少的錯(cuò)誤代碼
    • 在云中開發(fā)和測(cè)試

    翻譯自: https://www.javacodegeeks.com/2011/11/unit-testing-using-mocks-testing.html

    總結(jié)

    以上是生活随笔為你收集整理的使用模拟的单元测试–测试技术5的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。