编写干净的测试–从配置开始
很難為干凈的代碼找到一個好的定義,因為我們每個人都有自己的單詞clean的定義。 但是,有一個似乎是通用的定義:
干凈的代碼易于閱讀。
這可能會讓您感到有些驚訝,但是我認為該定義也適用于測試代碼。 使測試盡可能具有可讀性是我們的最大利益,因為:
- 如果我們的測試易于閱讀,那么很容易理解我們的代碼是如何工作的。
- 如果我們的測試易于閱讀,那么如果測試失敗(不使用調試器),很容易發現問題。
編寫干凈的測試并不難,但是需要大量的實踐,這就是為什么如此多的開發人員為此苦苦掙扎的原因。
我也為此感到掙扎,這就是為什么我決定與您分享我的發現的原因。
這是我的教程的第一部分,描述了我們如何編寫干凈的測試。 這次,我們將學習如何以簡單干凈的方式配置測試用例。
問題
假設我們必須使用Spring MVC Test框架為Spring MVC控制器編寫“單元測試”。 我們要測試的第一個控制器稱為TodoController ,但是我們還必須為應用程序的其他控制器編寫“單元測試”。
作為開發人員,我們知道重復的代碼是一件壞事。 在編寫代碼時,我們遵循“ 不要重復自己(DRY)”原則 ,該原則指出:
每條知識都必須在系統中具有單一,明確,權威的表示形式。
我懷疑這是開發人員經常在其測試套件中使用繼承的原因之一。 他們將繼承視為重用代碼和配置的廉價且簡便的方法。 這就是為什么他們將所有通用代碼和配置放入實際測試類的一個或多個基類。
讓我們看看如何使用該方法配置“單元測試”。
首先 ,我們必須創建一個抽象基類, 該基類可以配置Spring MVC Test框架,并通過實現setUpTest(MockMvc mockMvc)方法來確保其子類可以提供其他配置。
AbstractControllerTest類的源代碼如下所示:
import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WebUnitTestContext.class}) @WebAppConfiguration public abstract class AbstractControllerTest {private MockMvc mockMvc;@Autowiredprivate WebApplicationContext webAppContext;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();setupTest(MockMvc mockMvc)}protected abstract void setUpTest(MockMvc mockMvc); }其次 ,我們必須實現實際的測試類,該類創建所需的模擬和新的控制器對象。 TodoControllerTest類的源代碼如下所示:
import org.mockito.Mockito; import org.springframework.test.web.servlet.MockMvc;public class TodoControllerTest extends AbstractControllerTest {private MockMvc mockMvc;@Autowiredprivate TodoService serviceMock;@Overrideprotected void setUpTest(MockMvc mockMvc) {Mockito.reset(serviceMock);this.mockMvc = mockMvc;}//Add test methods here }這個測試類看起來很干凈,但是有一個主要缺陷:
如果我們想了解測試用例的配置方式,則必須閱讀TodoControllerTest和AbstractControllerTest類的源代碼。
這似乎是一個小問題,但這意味著我們必須將注意力從測試用例轉移到基類(或多個類)上。 這需要精神上的上下文切換,并且上下文切換非常昂貴 。
您可能當然會爭辯說,在這種情況下使用繼承的精神代價非常低,因為配置非常簡單。 的確如此,但是要記住,現實生活中的情況并非總是如此。
上下文切換的實際成本取決于測試類層次結構的深度和配置的復雜性。
解決方案
我們可以通過配置測試類中的所有測試用例來提高配置的可讀性。 這意味著我們必須:
- 將所需的注釋(例如@RunWith )添加到測試類。
- 將設置和拆卸方法添加到測試類。
如果我們遵循以下規則修改示例測試類,則其源代碼如下:
import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {WebUnitTestContext.class}) @WebAppConfiguration public class TodoControllerTest {private MockMvc mockMvc;@Autowiredprivate TodoService serviceMock;@Autowiredprivate WebApplicationContext webAppContext;@Beforepublic void setUp() {Mockito.reset(serviceMock);mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();}//Add test methods here }在我看來,我們的測試用例的新配置比舊的配置(分為TodoControllerTest和AbstractControllerTest類)看起來更加簡單和簡潔。
不幸的是,沒有什么是免費的。
這是一個權衡
每個軟件設計決策都需要權衡利弊。 這不是該規則的例外 。
在測試類中配置我們的測試用例具有以下好處:
另一方面,這種方法的缺點是:
如果我們唯一的目標是盡可能快地編寫測試,那么很明顯,我們應該消除重復的代碼和配置。
但是,這不是我唯一的目標。
我認為這種方法的優點勝于缺點的原因有兩個:
我在這件事上的立場是明確的。 但是,仍然存在一個非常重要的問題:
您會做出其他折衷嗎?
翻譯自: https://www.javacodegeeks.com/2014/05/writing-clean-tests-it-starts-from-the-configuration.html
總結
以上是生活随笔為你收集整理的编写干净的测试–从配置开始的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 知了吃什么食物 知了吃的食物有什么
- 下一篇: 什么叫跑酷运动 跑酷运动的简介