fusion构建器代码语法_构建器模式:适用于代码,适用于测试
fusion構建器代碼語法
我發(fā)現構建器設計模式偶爾在代碼中有用,但在測試中經常有用。 本文簡要概述了該模式,然后介紹了在測試中使用該模式的一個有效示例。 請參閱github中的代碼。
生成器模式的背景
根據GoF的書 ,構建器設計模式用于“將復雜對象的構造與其表示分離,以便同一構造過程可以創(chuàng)建不同的表示”。 像大多數GoF書中一樣,這是一個準確而乏味的描述。
喬什·布洛赫(Josh Bloch)在他的《 有效的Java》一書中,為建筑商提出了一種更有趣的用法。 他的方法試圖解決的問題是,當一個類具有“不止幾個”參數時,這些參數通常是通過構造函數設置的,其中許多參數可能是可選的。 典型的解決方案是
- 伸縮構造函數模式,在該模式中,您將為構造函數僅提供必需的參數,并為其他構造函數提供可選參數的變體,最終形成具有所有可選參數的構造函數。
這行得通,但是導致一個相當混亂的解決方案,該解決方案可能包含大量構造函數來覆蓋所有排列 - 一個簡單的構造函數(例如,僅用于必需的參數),由setter方法支持可選參數(JavaBeans方法)。 但是,這可能會使對象在構造過程中處于不一致狀態(tài),并且由于無法將字段定為final ,因此當然會阻止不變性。
- 使用一個生成器。 這是Bloch建議的方法。 客戶端創(chuàng)建一個生成器(通常使用無參數的構造器),然后在最終調用一個build方法之前,調用類似setter的方法來獲取感興趣的值(其余假定為默認值)。
幾年前,我參加了一次演講 ,其中Ted Young討論了通過將構建器模式用于測試對象的構建,使構建器模式更進一步,下面將討論這種方法。 [更新:請在此處查看Ted對這篇文章的回復]
使用Builder模式構建測試裝置
使用Builder可以更輕松,更清晰地創(chuàng)建測試裝置。
我通常使用此Builder方法進行測試的對象類型是域模型對象,例如Account,User,Widget或其他對象。 我支持使此類對象不可變 。
例如:
使用這樣的課程,您經常會遇到Bloch討論的問題。 在此示例中,我們有一個強制您設置所有值的構造函數,但是我們也可以有很多變體,其中一些值可以省略以使用默認值。 因此,為測試創(chuàng)建這樣一個類的實例可能會有些痛苦,如果它具有比這個簡單示例更多的字段,則情況會更加痛苦。 您甚至必須為可能不需要測試的字段提供值。 這也使得很難知道哪些值實際上是測試所需要的,哪些值純粹是為了編譯。
建設者可以提供幫助。
例
public class AccountBuilder {//account fields with default valuesInteger id = 1;String name = "default account name";AccountType type = AccountType.CHECKING;BigDecimal balance = new BigDecimal(0);DateTime openDate = new DateTime(2013, 01, 01, 0, 0, 0);Status status = Status.ACTIVE;public AccountBuilder() {}public AccountBuilder withId(Integer id) {this.id = id;return this;}public AccountBuilder withName(String name) {this.name = name;return this;}public AccountBuilder withType(AccountType type) {this.type = type;return this;}public AccountBuilder withBalance(BigDecimal balance) {this.balance = balance;return this;}public AccountBuilder withOpenDate(DateTime openDate) {this.openDate = openDate;return this;}public AccountBuilder withStatus(Status status) {this.status = status;return this;}public Account build() {return new Account(id, name, type, balance, openDate, status);} }現在,您可以創(chuàng)建一個Account對象,以更輕松地進行測試。
關于使用Builder進行測試的注意事項
- 默認值
構建器中使用的缺省值是避免出現異常的便利。 如果您的測試需要特定的測試值,則最好明確設置它們,而不要依賴于任何默認值。 它使您的測試意圖更加清晰,并且在您需要更改默認值(例如由于業(yè)務需求變化)而使無意中止測試的風險降到最低時。
- 非最終領域
域模型類本身是不可變的,因此具有最終字段。 根據設計,生成器中的所有字段都是非最終的。 因此,構建器不是線程安全的。 因此,請勿重復使用Builders; 而是為每個測試創(chuàng)建一個新實例。
- 方法順序不大
在大多數情況下,在構建器上調用方法的順序應該不重要,并且在調用build()之前不會構造該對象。 這使構建器更易于使用,并避免了意外的意外。
此經驗法則有明顯且可以接受的例外。
例如打電話
很傻,但被允許。 它只會為您提供類型檢查的權限。
很好,但是請嘗試避免引起更細微的混亂,例如,如果您的集合中可以添加某些內容,或者替換了整個集合(因此請清除以前的添加內容)。
使用Builder進行測試的優(yōu)勢
- 易于閱讀
以下聲明不是特別清楚:
Account account = new Account(1, "test", 10, ...);該聲明更加清晰:
Account account = new AccountBuilder().withId(1).withName("test").withBalance(10).build();正如Bloch所說,“ Builder模式模擬命名的可選參數”。
- 僅指定與您的測試實際相關的值
如果您的測試僅涉及帳戶余額和狀態(tài):
Account account = new AccountBuilder().withBalance(new BigDecimal(-100)).withStatus(Status.OVERDRAWN).build();與必須在Accounts構造函數中指定每個值相反。
- 創(chuàng)建無效對象的能力
域模型類的構造函數可能會(希望!)強迫您創(chuàng)建有效的對象。 在測試中,您可能要故意創(chuàng)建無效的對象以進行測試。
進一步的增強
便利方法
您可以為測試中使用的常見方案添加便捷方法。
例如
燈具類
除了使用Builder類之外,我還發(fā)現擁有一個關聯的Fixtures類很有用,該類提供用于測試的預構建實例。 這些可以利用Builder對象進行構造(盡管也沒有什么可以阻止您使用原始構造函數)。
例如
翻譯自: https://www.javacodegeeks.com/2013/06/builder-pattern-good-for-code-great-for-tests.html
fusion構建器代碼語法
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的fusion构建器代码语法_构建器模式:适用于代码,适用于测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Maven,Eclipse和Java 9
- 下一篇: 备案多个域名 删除一个会影响另一个吗(备