数据库 测试数据生成_测试数据生成器和对象母亲:另一种外观
數據庫 測試數據生成
在測試中構造對象通常是一項艱巨的工作,通常會產生大量可重復且難以閱讀的代碼。 有兩種用于處理復雜測試數據的常見解決方案: Object Mother和Test Data Builder 。 兩者都有優點和缺點,但是(巧妙地)結合可以為您的測試帶來新的質量。
注意:關于Object Mother和Test Data Builder ,已經有很多文章可以找到,因此我將使我的描述非常簡潔。
對象母親
不久,“ 對象母親”是一組工廠方法,使我們可以在測試中創建類似的對象:
// Object Mother public class TestUsers {public static User aRegularUser() {return new User("John Smith", "jsmith", "42xcc", "ROLE_USER");}// other factory methods}// arrange User user = TestUsers.aRegularUser(); User adminUser = TestUsers.anAdmin();每次需要數據變化稍有不同的用戶時,都會創建新的工廠方法,這會使“ Object Mother隨時間增長。 這是Object Mother的缺點之一。 可以通過引入Test Data Builder解決此問題。
測試數據生成器
Test Data Builder使用Builder模式在單元測試中創建對象。 一的簡短提醒Builder :
構建器模式是對象創建軟件設計模式。 […]構建器模式的目的是找到可伸縮構造函數反模式的解決方案。
讓我們看一下Test Data Builder的示例:
public class UserBuilder {public static final String DEFAULT_NAME = "John Smith";public static final String DEFAULT_ROLE = "ROLE_USER";public static final String DEFAULT_PASSWORD = "42";private String username;private String password = DEFAULT_PASSWORD;private String role = DEFAULT_ROLE;private String name = DEFAULT_NAME;private UserBuilder() {}public static UserBuilder aUser() {return new UserBuilder();}public UserBuilder withName(String name) {this.name = name;return this;}public UserBuilder withUsername(String username) {this.username = username;return this;}public UserBuilder withPassword(String password) {this.password = password;return this;}public UserBuilder withNoPassword() {this.password = null;return this;}public UserBuilder inUserRole() {this.role = "ROLE_USER";return this;}public UserBuilder inAdminRole() {this.role = "ROLE_ADMIN";return this;}public UserBuilder inRole(String role) {this.role = role;return this;}public UserBuilder but() {return UserBuilder.aUser().inRole(role).withName(name).withPassword(password).withUsername(username);}public User build() {return new User(name, username, password, role);} }在我們的測試中,我們可以如下使用構建器:
UserBuilder userBuilder = UserBuilder.aUser().withName("John Smith").withUsername("jsmith");User user = userBuilder.build(); User admin = userBuilder.but().withNoPassword().inAdminRole();上面的代碼看起來非常不錯。 我們擁有一個流暢的API,可以提高測試代碼的可讀性,并且可以肯定地消除了使用Object Mother需要多種工廠方法來處理測試中需要的對象變化的問題。
請注意,我添加了一些默認屬性值,這些默認值可能與大多數測試無關。 但是,由于我們將它們定義為公共常量,因此可以在斷言中使用它們。
注意:本文使用的示例相對簡單。 它用于可視化解決方案。
對象母親和測試數據生成器結合
兩種解決方案都不完美。 但是,如果我們將它們結合在一起怎么辦? 想象一下, Object Mother返回一個Test Data Builder 。 有了這個,您就可以在調用終端操作之前操縱構建器狀態。 這是一種模板。
看下面的例子:
public final class TestUsers {public static UserBuilder aDefaultUser() {return UserBuilder.aUser().inUserRole().withName("John Smith").withUsername("jsmith");}public static UserBuilder aUserWithNoPassword() {return UserBuilder.aUser().inUserRole().withName("John Smith").withUsername("jsmith").withNoPassword();}public static UserBuilder anAdmin() {return UserBuilder.aUser().inAdminRole().withName("Chris Choke").withUsername("cchoke").withPassword("66abc");} }現在, TestUsers提供了用于在我們的測試中創建類似測試數據的工廠方法。 它返回一個構建器實例,因此我們能夠根據需要在測試中快速而完美地修改對象:
UserBuilder user = TestUsers.aUser(); User admin = user.but().withNoPassword().build();好處是巨大的。 我們有一個用于創建相似對象的模板,如果我們需要在使用返回對象之前修改返回對象的狀態,則我們擁有構建器的強大功能。
豐富測試數據生成器
考慮以上內容時,我不確定是否真的需要單獨的Object Mother 。 我們可以輕松地將方法從Object Mother直接移動到Test Data Builder :
public class UserBuilder {public static final String DEFAULT_NAME = "John Smith";public static final String DEFAULT_ROLE = "ROLE_USER";public static final String DEFAULT_PASSWORD = "42";// field declarations omitted for readabilityprivate UserBuilder() {}public static UserBuilder aUser() {return new UserBuilder();}public static UserBuilder aDefaultUser() {return UserBuilder.aUser().withUsername("jsmith");}public static UserBuilder aUserWithNoPassword() {return UserBuilder.aDefaultUser().withNoPassword();}public static UserBuilder anAdmin() {return UserBuilder.aUser().inAdminRole();}// remaining methods omitted for readability}因此,我們可以在單個類中維護User數據的創建。
請注意,在此Test Data Builder是測試代碼。 如果我們在生產代碼中已經有一個生成器,那么創建一個Object Mother返回一個Builder實例聽起來是一個更好的解決方案。
可變對象呢?
當涉及可變對象時, Test Data Builder方法可能存在一些缺點。 在許多應用程序中,我主要處理可變對象(又稱為beans或anemic data model ),也許你們中的許多人也這樣做。
從理論上講, Builder模式用于創建不變的價值對象。 通常,如果我們處理可變對象,乍一看, Test Data Builder看起來就像是重復的:
// Mutable class with setters and getters class User {private String name;public String getName() { ... }public String setName(String name) { ... }// ... }public class UserBuilder {private User user = new User();public UserBuilder withName(String name) {user.setName(name);return this;}// other methodspublic User build() {return user;} }在測試中,我們可以創建一個如下用戶:
User aUser = UserBuiler.aUser().withName("John").withPassword("42abc").build();代替:
User aUser = new User(); aUser.setName("John"); aUser.setPassword("42abc");在這種情況下,創建Test Data Builder是一個折衷方案 。 它需要編寫更多需要維護的代碼。 另一方面,可讀性大大提高。
摘要
在單元測試中管理測試數據并非易事。 如果找不到合適的解決方案,那么最終將獲得大量難以理解和維護的樣板代碼。 另一方面,沒有解決該問題的靈丹妙藥。 我嘗試了許多方法。 根據問題的大小,我需要選擇一種不同的方法,有時在一個項目中結合使用多種方法。
您如何處理測試中的數據構建?
資源資源
- Petri Kainulainen: 編寫干凈的測試–被認為有害的新方法
- Growing Object-Oriented Software, Guided by Tests –第22章: Constructing Complex Test Data 。
翻譯自: https://www.javacodegeeks.com/2014/06/test-data-builders-and-object-mother-another-look.html
數據庫 測試數據生成
總結
以上是生活随笔為你收集整理的数据库 测试数据生成_测试数据生成器和对象母亲:另一种外观的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 测量时间:从Java到内核再到
- 下一篇: 网宿安全演武实验室成立,聚焦攻防体系研究