Autofixture: Accuse en lecture seule une propriété qui n'est pas en lecture seule

Créé le 4 juin 2013  ·  4Commentaires  ·  Source: AutoFixture/AutoFixture

Dans ma couche de domaine, j'ai la 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; }
}

L'identifiant est protégé en interne. Ceci est délibéré, qui génère l'ID est la base de données et doit être en lecture seule.
Mais dans la couche de test, il faut avoir accès au setter de cette propriété.

Donc, dans ma couche de domaine, j'ai ajouté l'attribut dans AssemblyInfo.cs :

[assembly: InternalsVisibleTo("MyTestLayer")]

Cela me permettra de définir l'Id dans la couche de tests mais pas dans la couche de domaine !

Dans la couche de test
nouveau Telefone().Id = 1; // Travaux!!

Dans la couche d'interface utilisateur
nouveau Telefone().Id = 1; // Pas de compilation ! Ne fonctionne pas !

Problème

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

Théoriquement, le code ci-dessus devrait fonctionner, mais lors de mon essai routier une erreur se produit :

La propriété "Id" est en lecture seule.

Toutes les propriétés Id s sont protected internal .

Dans le même fichier, le même test peut faire quelque chose comme :

nouveau Telefone().Id = 1; // Travaux!!
nouvel e-mail().Id = 1 ; // Travaux!!

question

Tous les 4 commentaires

Cela vous indique clairement que vous avez une _abstraction qui fuit_ dans votre modèle de domaine. Un modèle de domaine ne doit pas être conçu avec une technologie de limite particulière à l'esprit.

Ce problème particulier vous indique très clairement que votre modèle de domaine n'est _pas_ réutilisable.

InternalsVisibleTo n'a aucun effet car il permet uniquement l'accès à votre bibliothèque de test, mais AutoFixture est un assembly entièrement différent. Cela vous indique simplement que _aucun_ autre client ne pourra jamais réutiliser votre modèle de domaine.

La meilleure chose à faire est de reconsidérer la conception de votre API. Normalement, je ferais quelque chose comme ça :

``` c#
Téléphone de classe publique : IEntity
{
Téléphone public(int id)
{
this.Id = id;
}

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

}
```

Cela a généré beaucoup de discussions dans un groupe d'architecture que je suis.
Il y a un problème majeur avec cette approche :

  1. Qui est responsable de la génération de l'Id est la base de données, elle n'est générée que lorsque l'objet est enregistré.
  2. Quand je crée un nouvel objet, quel Id doit passer dans le constructeur ? Je ne peux pas mettre l'Id dans le constructeur.
  3. L'ID est un int séquentiel. La couche référentiel est la couche la plus proche du domaine. Pour générer l'Id, il faudrait faire quelque chose comme max (id) + 1 , puis définir l'Id de mon objet. Mais comment définir l'Id s'il est en lecture seule ?
  4. La seule façon de définir l'ID de dans une propriété ReadOnly est dans la classe elle-même ou en utilisant un proxy/réflexion

Convenu que ce sont tous des _problèmes_. Tous les quatre indiquent _fortement_ que le modèle de domaine dépend de la couche de persistance et ne peut pas fonctionner sans elle.

  1. Pourquoi la base de données devrait-elle attribuer des identifiants ? La seule exigence est qu'un identifiant soit unique. C'est pourquoi nous avons des GUID.
  2. Transmettez une nouvelle instance de Guid au constructeur.
  3. Pourquoi l'ID est-il séquentiel ? Il y a rarement une raison architecturale pour que les ID soient séquentiels.
  4. D'accord. Il y a une raison pour laquelle les modificateurs d'accès existent.

Je comprends le problème. Je ne peux pas changer le type PKs en Guid, cela fonctionnerait vraiment.

Je comprends maintenant que le problème n'est pas lié à AutoFixture, mais si cela vous intéresse. Je crée un exemple de projet pour en discuter.

Merci.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

mjfreelancing picture mjfreelancing  ·  4Commentaires

zvirja picture zvirja  ·  3Commentaires

zvirja picture zvirja  ·  4Commentaires

JoshKeegan picture JoshKeegan  ·  6Commentaires

zvirja picture zvirja  ·  8Commentaires