我在C#中使用MoQ进行一些单元测试/ BDD测试,而且我经常需要两次生成相同的对象(因为它可能会在字典中使用)。或者99%相同但只有不同的ID。
有没有办法克隆"模拟定义?或者生成具有相同定义的两个对象?
答案 0 :(得分:0)
您应该创建一个辅助方法,该方法构造接受一些参数来构造Mock对象。
[Test]
public void MyTest()
{
Mock<ITestObject> myMock = CreateObject(1);
ITestObject obj = myMock.Object;
}
private Mock<ITestObject> CreateObject(int id)
{
Mock<ITestObject> mock = new Mock<ITestObject>();
mock.SetupGet(o => o.ID).Returns(id);
return mock;
}
private interface ITestObject
{
int ID { get; set; }
}
答案 1 :(得分:0)
如果你只是需要一组数据来进行单元测试,你也可以考虑像AutoFixture这样的东西。对于要模拟的类,它可以与Moq一起使用。你教AutoFixture如何创建YourClass,你甚至可以设置像#34这样的规则;我的ID应该是大写字母的字符串,不超过X的数量。&#34;
然后你只使用自动混合。
var fixture = new Fixture();
var tetsClasses = fixture.CreateMany<TestClass>();
这只是为了给你一个想法。你可以用它做更多但更多,它与Moq一起玩得很好。
另一种方法是使用数据构建器模式来创建数据。因此,您可以从简单的事情开始,并在发现有关如何构建数据的新边缘情况时继续添加。只需在其上构建一个流畅的API,然后根据需要构建数据。
internal class TestClassBuilder<T> : where T : TestClass
{
int Id {get; set;}
public T WithId(int id)
{
this.Id = id;
return this;
}
public virtual T Build()
{
return new T()
{
if(this.Id)
Id = this.Id; // if you chose to set it, then assign it
else
Id = GetRandomId() // you can figure a solution here
}
}
}
然后称之为:
var stubOne = TestClassBuilder.WithId(1).Build();
如果需要,您可以扩展它以构建列表。
我喜欢数据构建器上的流畅API,因为您可以开始用您创建的方法讲述您的故事,并使您的编辑部分保持整洁。 示例:
var UnderAgeCustomer = new CustomerBuilder
.UnderAge
.WithFakeId
.InACrowd
.LooksYoung
.Build()
你甚至可以加上
public static implicit operator T(TestClassBuilder<T> builder)
{
return builder.Build();
}
并且您不需要一直使用.Build()部分(我认为构建会增加不必要的噪音)。只是不要尝试将其分配给var,它不会起作用。
TestClass MockTwo = TestClassBuilder.WithId(2);
我会说你也可以使用夹具模式跟踪所有这些...但是在它和数据库之间,你可以使用AutoFixture和Moq,如我所建议的那样:)