Autofixture: 为非只读属性指责只读

创建于 2013-06-04  ·  4评论  ·  资料来源: AutoFixture/AutoFixture

在我的域层有这样的类:

public class Telefone : IEntity
{
    public virtual int Id { get; protected internal set; }
    public virtual string Tipo { get; set; }
    public virtual string Numero { get; set; }
}

Id 受内部保护。 这是故意的,谁生成的Id是数据库,应该是只读的。
但是在测试层,必须可以访问这个属性的setter。

所以在我的域层中添加了 AssemblyInfo.cs 中的属性:

[assembly: InternalsVisibleTo("MyTestLayer")]

这将允许我在测试层而不是域层中设置 Id!

在测试层
new Telefone().Id = 1; // 有效!!

在 UI 层
new Telefone().Id = 1; // 不编译! 不行!

问题

var pessoa = fix.Build<Pessoa>()
    .With(p => p.Nome)
    .Do((pess) =>
    {
        fix.Build<Telefone>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Numero)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Telefones.Add);

        fix.Build<Email>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Endereco)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Emails.Add);
    })
    .OmitAutoProperties()
    .Create();

理论上,上面的代码应该可以工作,但是当我的路试时出现错误:

属性“Id”是只读的。

所有属性Id都是protected internal

在同一个文件中,同一个测试可以执行以下操作:

new Telefone().Id = 1; // 有效!!
新电子邮件().Id = 1; // 有效!!

question

所有4条评论

这清楚地告诉您,您的领域模型中有一个 _leaky 抽象_。 领域模型的设计不应考虑任何特定的边界技术。

这个特殊问题非常清楚地告诉您,您的领域模型_不可_重用。

InternalsVisibleTo没有效果,因为它只允许访问您的测试库,但 AutoFixture 是完全不同的程序集。 这只是告诉您 _no_ 其他客户端将永远能够重用您的域模型。

最好的做法是重新考虑您的 API 设计。 通常,我会做这样的事情:

``` c#
公共类电话:IEntity
{
公共电话(int id)
{
this.Id = id;
}

public virtual int Id { get; private set; }
public virtual string Tipo { get; set; }
public virtual string Numero { get; set; }

}
```

这在我关注的一组架构中引起了很多讨论。
这种方法有一个主要问题:

  1. 负责生成Id的是数据库,只有在保存对象时才会生成。
  2. 当我创建一个新对象时,哪个Id必须传入构造函数? 我不能把 Id 放在构造函数中。
  3. Id 是一个整数序列。 存储库层是域的最近层。 要生成 Id 将执行类似max (id) + 1 ,然后设置我的对象的 Id。 但是如果它是只读的,如何设置Id?
  4. 在 ReadOnly 属性中设置 Id 的唯一方法是在类本身内或使用代理/反射

同意这些都是_问题_。 这四个都_强烈_表明域模型依赖于持久层,没有它就不能工作。

  1. 数据库为什么要分配 ID? 唯一的要求是 ID 是唯一的。 这就是我们有 GUID 的原因。
  2. 将新的 Guid 实例传递给构造函数。
  3. 为什么ID是顺序的? ID 是连续的,很少有任何架构上的原因。
  4. 同意。 存在访问修饰符是有原因的。

我明白这个问题。 我不能将 PKs 类型更改为 Guid,真的可以。

我现在明白这个问题与 AutoFixture 无关,但如果您有兴趣。 我创建了一个示例项目来讨论这个问题。

谢谢。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

zvirja picture zvirja  ·  3评论

ploeh picture ploeh  ·  3评论

malylemire1 picture malylemire1  ·  7评论

zvirja picture zvirja  ·  8评论

Ephasme picture Ephasme  ·  3评论