2010-05-17 19 views
14

Quelle est la méthode correcte pour traiter les interfaces avec les propriétés set-only d'exposition avec Moq? Auparavant, j'ai ajouté l'autre accesseur mais cela a saigné dans mon domaine trop loin avec des instructions aléatoires throw new NotImplementedException() partout.Moq comment corriger correctement les propriétés du jeu uniquement

Je veux juste faire quelque chose de simple comme:

mock.VerifySet(view => view.SetOnlyValue, Times.Never());

Mais cela donne une erreur de compilation de The property 'SetOnlyValue' has no getter

+0

Je suis confus, quel est le but du test si le compilateur détecte le fait que vous essayez d'appeler un getter sur une propriété en écriture seule? Je suis sûr qu'il me manque quelque chose ici, peut-être une clarification de OP? –

+1

@Igor Zevaka et autres: 'view => view.SetOnlyValue 'génère' La propriété' SetOnlyValue 'n'a pas de getter'. C'est parce que ce morceau de code est interprété comme un appel à un getter. Dans le cas de lecture-écriture, 'VerifySet' parcourt l'expression et détermine que ce qui est recherché est une attente sur le setter de la propriété. Dans le cas d'écriture seule, cela se traduit par une erreur de compilation. Nous devons supposer que l'OP n'est pas stupide ici et n'essaye pas de causer du travail pour lui-même et demande plutôt "comment éviter d'avoir à faire des déchets supplémentaires". –

+2

Oh, je comprends. Il s'agissait donc de mettre en place une vérification dans moq qui ne reposait pas sur une propriété nécessitant un getter, n'est-ce pas? –

Répondre

18
public class Xyz 
{ 
    public virtual string AA { set{} } 
} 
public class VerifySyntax 
{ 
    [Fact] 
    public void ThisIsHow() 
    { 
     var xyz = new Mock<Xyz>(); 
     xyz.Object.AA = "bb"; 
     // Throws: 
     xyz.VerifySet(s => s.AA = It.IsAny<string>(), Times.Never()); 
    } 
} 
public class SetupSyntax 
{ 
    [Fact] 
    public void ThisIsHow() 
    { 
     var xyz = new Mock<Xyz>(); 
     xyz.SetupSet(s => s.AA = It.IsAny<string>()).Throws(new InvalidOperationException()); 
     Assert.Throws<InvalidOperationException>(() => xyz.Object.AA = "bb"); 
    } 
} 
+0

+1 - Ayant lu ceci, j'ai supprimé ma réponse car il semble être ce que l'OP veut. – Lee

+0

@Lee: Cool, ta (Je sais que j'ai fait une double lecture de la question aussi! –

+0

Merci Ruben, je n'aurais jamais décidé au hasard de mettre une expression It.IsAny à côté d'une ligne que resharper dit être une erreur de compilation! –

2

Merci Ruben!

Et pour aider quelqu'un avec un VB.Net Gotcha c'est le même code VB.Net:

Public Interface Xyz 
    WriteOnly Property AA As String 
End Interface 
Public Class VerifySyntax 
    <Fact()> 
    Public Sub ThisIsHow() 
     Dim xyz = New Mock(Of Xyz) 
     xyz.Object.AA = "bb" 
     ' Throws: 
     xyz.VerifySet(Sub(s) s.AA = It.IsAny(Of String)(), Times.Never()) 
    End Sub 
End Class 
Public Class SetupSyntax 
    <Fact()> 
    Public Sub ThisIsHow() 
     Dim xyz = New Mock(Of Xyz) 
     xyz.SetupSet(Sub(s) s.AA = It.IsAny(Of String)()).Throws(New InvalidOperationException()) 
     Assert.Throws(Of InvalidOperationException)(Sub() xyz.Object.AA = "bb") 
    End Sub 
End Class 

important ici est que vous ne pouvez pas utiliser une seule ligne Fonction lambda car cela sera interprété comme une expression qui renvoie une valeur, plutôt que l'instruction d'assignation que vous recherchez. Ce est depuis VB.Net utilise le signe égal unique non seulement pour l'affectation, mais aussi pour la comparaison de l'égalité, et ainsi essayer de faire

 xyz.VerifySet(Function(s) s.AA = It.IsAny(Of String)(), Times.Never()) 

sera interprété comme une comparaison booléenne de la valeur s.AA et la It.IsAny (Of String)(), invoquant ainsi le getter, ce qui entraînera à nouveau une erreur de compilation. A la place, vous voulez utiliser un Sub lambda (ou éventuellement une fonction multiligne lambda).

Si vous avez un getter sur la propriété, cependant, une fonction lambda fonctionnera toujours.