Autofixture: Acusa somente leitura por uma propriedade que não é somente leitura

Criado em 4 jun. 2013  ·  4Comentários  ·  Fonte: AutoFixture/AutoFixture

Na minha camada de domínio temos a classe:

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

O Id é protegido interno. Isso é proposital, quem gera o Id é o banco de dados e deve ser ReadOnly.
Já na camada de teste, deve-se ter acesso ao setter desta propriedade.

Então, em minha camada de domínio, adicionei o atributo em AssemblyInfo.cs:

[assembly: InternalsVisibleTo("MyTestLayer")]

Isso me permitirá definir o Id na camada de testes, mas não na camada de domínio!

Na camada de teste
novo Telefone (). Id = 1; // Trabalho!!

Na camada da IU
novo Telefone (). Id = 1; // Não compilar! Não funciona!

Problema

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

Teoricamente, o código acima deve funcionar, mas quando meu teste de estrada ocorre um erro:

A propriedade "Id" é somente leitura.

Todas as propriedades Id s são protected internal .

No mesmo arquivo, o mesmo teste pode fazer algo como:

novo Telefone (). Id = 1; // Trabalho!!
novo e-mail (). Id = 1; // Trabalho!!

question

Todos 4 comentários

Isso indica claramente que você tem uma _ abstração vazada_ em seu Modelo de Domínio. Um Modelo de Domínio não deve ser projetado com nenhuma tecnologia de fronteira específica em mente.

Esse problema específico está dizendo claramente que seu Modelo de Domínio _não_ pode ser reutilizado.

InternalsVisibleTo não tem efeito porque só permite o acesso à sua biblioteca de teste, mas o AutoFixture é um assembly totalmente diferente. Isso apenas informa que _nenhum_ outro cliente poderá reutilizar seu Modelo de Domínio.

O melhor curso de ação é reconsiderar o design da API. Normalmente, eu faria algo assim:

`` `c #
classe pública Telefone: IEntity
{
telefone público (int id)
{
this.Id = id;
}

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

}
`` `

Isso gerou muita discussão em um grupo de arquitetura que sigo.
Há um grande problema com essa abordagem:

  1. Quem é o responsável por gerar o Id é o banco de dados, ele só é gerado quando o objeto é salvo.
  2. Quando eu crio um novo objeto, qual Id deve passar no construtor? Não consigo colocar o Id no construtor.
  3. O Id é um int sequencial. A camada de repositório é a camada mais próxima do Domínio. Para gerar o Id, faria algo como max (id) + 1 e, em seguida, definiria o Id do meu objeto. Mas como definir o Id se for somente leitura?
  4. A única maneira de definir o Id em uma propriedade ReadOnly é dentro da própria classe ou usando um proxy / reflexão

Concordou que todos esses são _problemas_. Todos os quatro indicam _fortemente_ que o Modelo de Domínio depende da camada de persistência e não pode funcionar sem ela.

  1. Por que o banco de dados deve atribuir IDs? O único requisito é que um ID seja exclusivo. É por isso que temos GUIDs.
  2. Passe uma nova instância de Guid para o construtor.
  3. Por que o ID é sequencial? Raramente há qualquer razão arquitetônica para que os IDs sejam sequenciais.
  4. Concordou. Há uma razão para a existência de modificadores de acesso.

Eu entendo o problema. Não consigo mudar o tipo de PKs para Guid, realmente funcionaria.

Eu entendo agora que o problema não está relacionado ao AutoFixture, mas se você estiver interessado. Eu crio um projeto de amostra para discutir isso.

obrigado.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

tiesmaster picture tiesmaster  ·  7Comentários

Eldar1205 picture Eldar1205  ·  5Comentários

malylemire1 picture malylemire1  ·  7Comentários

zvirja picture zvirja  ·  4Comentários

ploeh picture ploeh  ·  3Comentários