生成相同模拟的两个对象

Generate two object of the same mock

我在 C# 中使用 MoQ 来做一些单元 tests/BDD 测试,我经常需要生成相同的对象两次(因为它可能会在字典中使用)。或者 99% 相同但 ID 不同的东西。

有没有办法 "clone" Mock 定义?或者生成两个具有相同定义的对象?

您应该创建一个辅助方法来构造它,该方法接受一些参数来构造 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; }
}

如果你只需要一组数据来进行单元测试,你也可以考虑像 AutoFixture 这样的东西。如果您想模拟 类,它可以与 Moq 一起使用。您教 AutoFixture 如何创建 YourClass,您甚至可以设置像 "my IDs should be strings with capital letters and no more than X amount of them."

这样的规则

那你就用autofixture.

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();

如果需要,您可以扩展它来构建列表。

我喜欢数据生成器上的流利 APIs,因为您可以开始使用您创建的方法来讲述您的故事,并且它使您的排列部分保持整洁。 示例:

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 :)