49 votes

Besoin d'aide pour mieux comprendre Moq

J'ai été à la recherche à la Moq documentation et les commentaires sont trop courtes pour moi de comprendre chacune des choses qu'il peut faire.

La première chose que je ne comprends pas est - It.IsAny<string>(). //example using string

Est-il un avantage de l'utilisation de ce plus juste de mettre un peu de valeur? Je sais que les gens disent à utiliser si vous n'avez pas de soins sur la valeur, mais si vous n'avez pas de soins sur la valeur que tu ne peux pas faire "un" ou quelque chose? Cela ressemble plus à taper.

Deuxièmement, quand il serait un exemple de quand vous ne se soucient pas de la valeur? J'ai pensé Moq besoins de la valeur à respecter les trucs.

Je ne comprends pas ce qu' It.Is<> est pour tous ou comment l'utiliser. Je ne comprends pas l'exemple et il essaie de montrer.

Ensuite, je ne comprends pas quand utiliser Times (et de ses AtMost méthodes et similaires). Pourquoi vous limitez le nombre de fois que quelque chose est mis en place? J'ai quelques AppConfig de la valeur que je dois utiliser deux fois. Pourquoi voudrais-je à ce limiter à, disons, une fois? Ce serait tout simplement faire le test échoue. Est-ce pour empêcher d'autres personnes de l'ajout d'une autre de votre code ou quelque chose?

Je ne comprends pas comment utiliser mock.SetupAllProperties(); Que faut-il configurer les propriétés avec?

Je ne suis pas aussi pourquoi il y a tellement de façons différentes de mettre en place une propriété et quelles sont leurs différences. La documentation a:

SetupGet(of property)
SetupGet<TProperty>

J'ai remarqué que beaucoup de choses dans Moq montre () et <> - quelle est la différence entre eux et quelles seraient-elles en cours d'utilisation?

Aussi je ne comprends pas pourquoi ils ont SetupGet. Ne seriez-vous pas utiliser SetupSet de définir une propriété? SetupSet a cinq différentes manières de l'utiliser dans la documentation. Plus un autre qu'on appelait SetupProperty. Donc je ne comprends pas pourquoi ils sont si nombreux.

Sur une note de côté, je me demande si les variables utilisées dans les lambdas sont indépendants des autres lambdas. E. g.:

mock.setup(m => m.Test);
stop.setup(m => m.Test);

Serait-ce ok ou y aurait-il un conflit entre la variable m?

Enfin, j'ai été en regardant cette vidéo et je me demandais si il montre Visual Studio. Son Intellisense est différent. Une ampoule s'ouvrira pour lui (je suis heureux mine de ne pas, comme il apporte des souvenirs douloureux de netbeans), et il y a de lignes, allant d'une accolade d'ouverture à l'accolade de fermeture et etc.

Merci :)

113voto

John Foster Points 5411

C'.IsAny / Elle.Est

Ceci peut être utile lorsque vous êtes à l'adoption d'un nouveau type de référence dans le code sous test. Par exemple, si vous aviez une méthode le long des lignes de:-

public void CreatePerson(string name, int age) {
    Person person = new Person(name, age);
    _personRepository.Add(person);
}

Vous pouvez consulter l'ajout de méthode a été appelée sur le référentiel

[Test]
public void Create_Person_Calls_Add_On_Repository () {
    Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
    PersonManager manager = new PersonManager(mockRepository.Object);
    manager.CreatePerson("Bob", 12);
    mockRepository.Verify(p => p.Add(It.IsAny<Person>()));
}

Si vous vouliez faire ce test plus explicite, vous pouvez l'utiliser.Est de fournir un prédicat de l'objet personne doit correspondre à

[Test]
public void Create_Person_Calls_Add_On_Repository () {
    Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
    PersonManager manager = new PersonManager(mockRepository.Object);
    manager.CreatePerson("Bob", 12);
    mockRepository.Verify(pr => pr.Add(It.Is<Person>(p => p.Age == 12)));
}

De cette façon, le test à travers une exception si la personne objet qui a été utilisé pour appeler la méthode add de ne pas avoir l'âge de la propriété 12.

Fois

Si vous aviez une méthode le long des lignes de:-

public void PayPensionContribution(Person person) {
    if (person.Age > 65 || person.Age < 18) return;
    //Do some complex logic
    _pensionService.Pay(500M);
}

L'une des choses que vous pouvez tester, c'est que la méthode de paiement n'est pas appelé quand une personne âgée de plus de 65 ans est passé dans la méthode

[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
    Mock<IPensionService> mockPensionService = new Mock<IPensionService>();
    Person p = new Person("test", 66);
    PensionCalculator calc = new PensionCalculator(mockPensionService.Object);
    calc.PayPensionContribution(p);
    mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}

De même, il est possible d'imaginer des situations où vous êtes une itération sur une collection et l'appel d'une méthode pour chaque élément de la collection et vous souhaitez assurez-vous qu'il est appelé un certain nombre de fois, d'autres fois, vous n'avez simplement pas de soins.

SetupGet / SetupSet

Ce que vous devez être conscients de ces gars-là, c'est qu'ils reflètent la façon dont votre code est en interaction avec la fantaisie plutôt que de la façon dont vous êtes en train de configurer la maquette

public static void SetAuditProperties(IAuditable auditable) {
    auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}

Dans ce cas, le code est le réglage de la ModifiedBy propriété de la IAuditable instance alors qu'il devient la propriété de Nom de l'instance actuelle de IPrincipal

[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
    Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
    Mock<IAuditable> mockAuditable = new Mock<IAuditable>();

    mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");

    Thread.CurrentPrincipal = mockPrincipal.Object;
    AuditManager.SetAuditProperties(mockAuditable.Object);

    mockPrincipal.VerifyGet(p => p.Identity.Name);
    mockAuditable.VerifySet(a => a.ModifiedBy = "test");
}

Dans ce cas, nous sommes en paramètre le nom de la propriété sur la maquette de IPrincipal si elle renvoie la valeur "test" lors de la lecture est appelée sur le Nom de la propriété de l'Identité nous ne sommes pas à la définition de la propriété elle-même.

SetupProperty / SetupAllProperties

En regardant le test ci-dessus si il a été changé à lire

[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
    Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
    Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
    mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");

    var auditable = mockAuditable.Object;

    Thread.CurrentPrincipal = mockPrincipal.Object;
    AuditManager.SetAuditProperties(auditable);

    Assert.AreEqual("test", auditable.ModifiedBy);
}

Le test échoue. C'est parce que le proxy créé par Moq ne fait pas faire quoi que ce soit dans la méthode set de propriété sauf si vous lui dites. Dans les affecter à l'objet fantaisie ressemble un peu à ça

public class AuditableMock : IAuditable {
     public string ModifiedBy { get { return null; } set { } }

}

Pour obtenir le test à passer, vous avez à dire Moq pour l'installation de la propriété la propriété standard de comportement. Vous pouvez le faire en appelant SetupProperty et la fantaisie qui donne un aspect plus

public class AuditableMock : IAuditable {
     public string ModifiedBy { get; set; }
}

et le test ci-dessus passerait comme la valeur "test" serait désormais stockés à l'encontre de la maquette. Lorsque les moqueries des objets complexes que vous pourriez vouloir faire cela pour toutes les propriétés, d'où le raccourci SetupAllProperties

Enfin, l'ampoule dans l'IDE est la resharper plugin.

5voto

Andy_Vulhop Points 2347

Si vous ne vous souciez pas de la valeur exacte d'une propriété, il est préférable d'utiliser .IsAny parce que vous êtes explicite sur le fait que la valeur exacte n'est pas importante. Si vous le codez en dur comme "abc", il n'est pas clair si votre code que vous testez dépend de commencer par "a" ou de se terminer par "c" ou d'avoir 3 caractères, etc. etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X