使用私有构造函数和静态创建方法以及私有 id 属性模拟类

dra*_*tik 4 c# unit-testing mocking autofixture fakeiteasy

我正在尝试使用 AutoFixture 来简化我的生活。

我如何模拟一个班级

  • 非公共构造函数和
  • 非公共 ID 和
  • 静态“创建”方法?

例子

public class User
{
    private User(){}

    /// <summary>
    ///     Created by Database...
    /// </summary>
    public long? Id { get; protected set; }

    public string Name { get; protected set; }

    public static User Create(string name)
    {
        var user = new User {Name = name};
        return user;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试过使用 Factory 和 SpecimenBuilder 的组合:

    [Fact]
    public void CreatingUserWithId_Should_Work_UsingFactoryAndSpecimenBuilder()
    {
        IFixture fixture = new Fixture().Customize(new AutoFakeItEasyCustomization());
        fixture.Customizations.Add(new UserBuilder());
        fixture.Customize<User>(o => o.FromFactory(() => User.Create("foo")));

        var user = fixture.Create<User>();

        user.Should().NotBeNull();
        user.Id.Should().HaveValue();
    }
Run Code Online (Sandbox Code Playgroud)

public class UserBuilder : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        var pi = request as PropertyInfo;
        if (pi == null) return new NoSpecimen(request);

        // The following code only works for public properties... :-(
        if (pi.Name == "Id" && pi.PropertyType == typeof (long?)) return 42;

        return new NoSpecimen(request);
    }
}
Run Code Online (Sandbox Code Playgroud)

演示 C# 解决方案可在https://github.com/draptik/MockingStaticCreate 获得

感谢任何指点,

帕特里克

Rub*_*ink 5

AF 将做正确的事情(User.Create()使用匿名名称 arg),无需任何自定义。

唯一缺少的位是设置Id. 这是一个您必须自己回答的问题——您的消费代码首先应该如何做到这一点?当你决定后,你可以做fixture.Customize<User>( c => c.FromFactory( User.Create).Do( x => ???)

也许你可以考虑暴露一个也需要一个的ctor id。然后,你可以做一个Customize<User>... GreedyConstructorQuery

如果您的 ORM 正在做一些古怪的反射并且您喜欢它和/或无法绕过它,您可以选择是否应该为您的测试:

a)也这样做 - 如果这与给定的测试或测试集相关

b) 认为这是可行的

关于将模拟和值混合到实体或值对象中 - 不要这样做(Mark Seemann 的命令与查询文章可能对您有所帮助)。您似乎需要/想要这样做的事实使您似乎在个别测试中试图过于雄心勃勃 - 您是否正在寻找最简单的测试方法并尝试以Assert最少的设置进行单一测试。

去购买GOOS 的书——它会帮助你找到平衡这些权衡的方法。