在我的域层有这样的类:
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; // 有效!!
这清楚地告诉您,您的领域模型中有一个 _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; }
}
```
这在我关注的一组架构中引起了很多讨论。
这种方法有一个主要问题:
max (id) + 1
,然后设置我的对象的 Id。 但是如果它是只读的,如何设置Id?同意这些都是_问题_。 这四个都_强烈_表明域模型依赖于持久层,没有它就不能工作。