使用私有 ctor 和静态创建方法和私有 id 属性模拟类

本文关键字:id 属性 模拟类 方法 创建 ctor 静态 | 更新日期: 2023-09-27 17:56:29

我正在尝试使用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;
    }
}

我尝试使用工厂和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();
    }

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);
    }
}
演示

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

感谢任何指示,

帕特里克

使用私有 ctor 和静态创建方法和私有 id 属性模拟类

AF

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

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

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

如果你的ORM正在做一些古怪的反思,而你喜欢这样和/或无法绕过它,你可以选择是否应该为你的测试:

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

b) 认为这是行之有效的

关于混合模拟和将值输入到实体或值对象 - 不要这样做(Mark Seemann 的命令与查询文章可能会在这里为您提供帮助)。您似乎需要/想要这样做的事实使您似乎在单个测试中过于雄心勃勃 - 您是否找到了最简单的测试内容,并尝试用最少的设置进行单一Assert测试一件事。

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