前言
在写测试用例时,我们经常需要创建模拟数据,在C#中常用的方式是使用nuget包Bogus
。
Bogus可以按照一定规则生成随机数据,示例代码如下:
public class User
{public string Name { get; set; }public int Age { get; set; }public string Phone { get; set; }
}// 用户数据生成规则
var fakerUser = new Faker<User>() .RuleFor(p => p.Name, f => f.Name.FullName()) // 随机姓名.RuleFor(p => p.Age, f => f.Random.Number(1, 100)) // 随机年龄(1-100岁).RuleFor(p => p.Phone, p => p.Phone.PhoneNumber("1##########")) // 随机手机号;// 生成测试用户
var user = fakerUser.Generate();
但是,在测试用例中,我只需关注特定属性的值,其它属性有不有值无所谓;而且每个测试用例关注的属性和规则也不一样。
这样就可能导致大量的重复性模拟数据生成代码。
如何减少这些业务逻辑之外代码的干扰呢?
建造者模式
建造者模式,是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在C#中,我们最常用的建造者模式实现就是StringBuilder
:
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Hello");
stringBuilder.AppendFormat("{0} {1}","My","IO");
var result = stringBuilder.ToString();
它通过叠加使用多个Apend
方法,最后组合成需要的字符串。
实现
利用建设者模式,我们创建UserBuilder
,指定特定属性的规则,并生成User对象,而无需明确指定所有这些属性:
public class UserBuilder
{private readonly Faker<User> _fakerUser = new Faker<User>().RuleFor(p => p.Name, f => f.Name.FullName()) .RuleFor(p => p.Age, f => f.Random.Number(1, 100)) .RuleFor(p => p.Phone, p => p.Phone.PhoneNumber("1##########")); public UserBuilder RuleForAge(int min, int max){_fakerUser.RuleFor(p => p.Age, f => f.Random.Number(min, max));return this;}public UserBuilder RuleForPhone(string format){_fakerUser.RuleFor(p => p.Phone, p => p.Phone.PhoneNumber(format));return this;}public User Build(){return _fakerUser.Generate();}
}
现在,代码是不是更容易理解了:
//关注的是Phone
var user = new UserBuilder().RuleForPhone("54321########").Build();
结论
使用建造者模式封装Bogus的使用,可以让创建模拟数据代码更加干净清晰!
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“