2009-09-17 11 views
14

Je suis novice en matière de Moq et d'apprentissage.Moq: Spécification des valeurs de retour dans le cadre des attentes

Je dois tester qu'une méthode renvoie la valeur attendue. J'ai mis en place un exemple noddy pour expliquer mon problème. Cela échoue lamentablement avec:

"ArgumentException: L'expression n'est pas un appel de méthode: c => (c.DoSomething (" Jo " "Blog", 1) = "OK")"

Pouvez-vous corriger ce que je fais mal?

[TestFixtureAttribute, CategoryAttribute("Customer")] 
public class Can_test_a_customer 
{ 
    [TestAttribute] 
    public void Can_do_something() 
    { 
     var customerMock = new Mock<ICustomer>(); 

     customerMock.Setup(c => c.DoSomething("Jo", "Blog", 1)).Returns("OK"); 

     customerMock.Verify(c => c.DoSomething("Jo", "Blog", 1)=="OK"); 
    } 
} 

public interface ICustomer 
{ 
    string DoSomething(string name, string surname, int age); 
} 

public class Customer : ICustomer 
{ 
    public string DoSomething(string name, string surname, int age) 
    { 
     return "OK"; 
    } 
} 

En un mot: si je voulais tester une méthode comme celle-ci, et je sais que je suis dans l'attente d'un retour « OK », comment pourrais-je écrire en utilisant Moq?

Merci pour vos suggestions.

Répondre

15
  1. Vous avez besoin d'un sujet de test qui interagit avec les objets fantaisie (sauf si vous écrivez un test de l'apprenant pour Moq.) J'ai écrit un simple ci-dessous
  2. attentes de configuration Vous sur l'objet maquette, en précisant exactement arguments (stricts - si vous souhaitez ofcourse, utilisez autre Is.Any<string> pour accepter toute chaîne) et spécifier des valeurs de retour le cas échéant
  3. votre sujet de test (dans le cadre de l'étape de loi du test) appellera sur votre maquette
  4. vous affirmer que le sujet du test s'est comporté comme requis. La valeur de retour des méthodes fictives sera utilisée par le sujet du test - vérifiez-la via l'interface publique du sujet du test.
  5. Vous vérifiez également que toutes les attentes que vous avez spécifiées ont été satisfaites - toutes les méthodes que vous attendiez d'être appelées ont bien été appelées.

.

[TestFixture] 
public class Can_test_a_customer 
{ 
    [Test] 
    public void Can_do_something() 
    { 
    //arrange 
    var customerMock = new Moq.Mock<ICustomer>(); 
    customerMock.Setup(c => c.DoSomething(Moq.It.Is<string>(name => name == "Jo"), 
     Moq.It.Is<string>(surname => surname == "Blog"), 
     Moq.It.Is<int>(age => age == 1))) 
     .Returns("OK"); 

    //act 
    var result = TestSubject.QueryCustomer(customerMock.Object); 

    //assert 
    Assert.AreEqual("OK", result, "Should have got an 'OK' from the customer"); 
    customerMock.VerifyAll(); 
    } 
} 

class TestSubject 
{ 
    public static string QueryCustomer(ICustomer customer) 
    { 
    return customer.DoSomething("Jo", "Blog", 1); 
    } 
} 
+1

Exactement. Son test n'a pas de sujet de test, ce qui a conduit à la confusion. Vous testez un sujet de test, pas un simulacre. –

+0

J'apprends aussi, je pense que j'ai la tête enroulée autour de ceci, pourriez-vous confirmer s'il vous plaît. Dans cet exemple 'DoSomething' pourrait renvoyer' jabberwocky' mais parce que votre '// arrangez .Setup' est dit à' .Return ("OK") 'c'est l'assertion. Je comprends que le test est de s'assurer que 'TestSubject' fonctionne comme prévu, et qu'il n'y a pas de test sur' Customer' ici. Si tel est le cas, pourquoi affirmer la valeur de retour de 'Client' et pas seulement' .Returns ("SUCCESS") 'ou une autre chaîne générique pour vérifier que' TestSubject' s'est terminé avec succès? – JabberwockyDecompiler

+0

@JabberwockyDecompiler - c'était juste un exemple de test où la sortie dépendait d'un collaborateur (raillé) .. par exemple, le client pouvait retourner "Sam" et la méthode/classe testée pouvait renvoyer "Hello Sam!". Pour tester ceci: vous devrez configurer le simulacre pour retourner "Sam" dans le test. – Gishu

11

Mock<T>.Verify ne retourne pas la valeur renvoyée par l'appel de méthode, donc vous ne pouvez pas simplement le comparer à la valeur attendue en utilisant "==".

En fait, no overload of Verify renvoie n'importe quoi, car vous ne devriez jamais avoir besoin de vérifier qu'une méthode mockée renvoie une valeur spécifique. Après tout, vous étaient responsables de la mise en place pour retourner cette valeur en premier lieu! Les valeurs de retour des méthodes simulées sont là pour être utilisées par le code que vous testez - vous ne testez pas les simulacres.

Utilisez Verify pour confirmer que la méthode a été appelée avec les arguments attendus ou qu'une propriété a été affectée à une valeur attendue. Les valeurs de retour des méthodes et des propriétés mockées ne sont pas importantes au moment où vous arrivez à la phase «assertion» de votre test.

2

Vous faites la même chose que ce gars était en train de faire ici: How to Verify another method in the class was called using Moq

Vous moquez ce que vous testez. Cela n'a pas de sens. L'utilisation de Mocks est pour l'isolation. Votre test Can_Do_Something passe toujours. Peu importe ce que. Ce n'est pas un bon test.Regardez de plus près le test de Gishu ou le test que j'ai proposé dans la question SO liée.

+0

Salut, vous avez absolument raison, je suis nouveau dans le monde de la moquerie Alors est-il correct de dire que se moquer d'une méthode est juste pour vérifier que la méthode a été appelée ou une propriété a été définie pour ne pas vérifier ce que la méthode retourne. Est-ce correct? –

+1

Une simulation est conçue pour vérifier une méthode externe ET isoler le code que vous testez * réellement *. Par exemple, si votre classe essayait d'accéder à une base de données, vous vous moquez de votre classe d'accès aux données pour que non seulement elle renvoie des résultats cohérents, mais que votre test ne nécessite pas l'exécution d'une base de données. Vous isolez la classe que vous testez des autres modifications apportées aux autres classes que vous pourriez créer. –

Questions connexes