2010-05-17 16 views
14

¿Cuál es la forma correcta de tratar con interfaces las propiedades de solo exposición con Moq? Anteriormente, agregué el otro acceso pero esto ha sangrado demasiado en mi dominio con declaraciones aleatorias throw new NotImplementedException() en todas partes.Moq cómo simular correctamente establecer solo las propiedades

sólo quiero hacer algo tan simple como:

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

Pero esto produce un error de compilación de The property 'SetOnlyValue' has no getter

+0

Estoy confundido, ¿cuál es el propósito de la prueba si el compilador detecta el hecho de que intentas llamar a un getter en una propiedad de solo escritura? Estoy seguro de que me falta algo aquí, tal vez una aclaración de OP? –

+1

@Igor Zevaka y otros: 'view => view.SetOnlyValue 'genera' La propiedad' SetOnlyValue 'no tiene getter'. Esto se debe a que este fragmento de código se interpreta como una llamada a un getter. En el caso de lectura y escritura, 'VerifySet' recorre la expresión y se da cuenta de que lo que se busca es una expectativa para el que establece la propiedad. En el caso de solo escritura, esto se ejecuta en un error de compilación. Tenemos que suponer que el OP no es estúpido aquí y no está tratando de causar trabajo por sí mismo y, en cambio, se está preguntando '¿cómo puedo evitar tener que hacer más basura'? –

+2

Oh lo entiendo. Entonces, se trataba de configurar una verificación en moq que no dependiera de una propiedad que requiera getter, ¿correcto? –

Respuesta

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 - Después de leer esto, borré mi respuesta ya que parece ser lo que quiere el OP. – Lee

+0

@Lee: Genial, ta (¡Sé que hice una doble lectura al leer la pregunta también!) –

+0

Gracias Rubén, ¡nunca habría decidido al azar poner una expresión It.IsAny al lado de una línea que, según refritura, es un error de compilación! –

2

Gracias Ruben!

Y para ayudar a alguien con un VB.Net Gotcha este es el mismo código en 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 

importante aquí es que usted no puede utilizar una función de una sola línea lambda, ya que esto se interpretará como una expresión que devuelve un valor, en lugar de la declaración de asignación que está buscando. Esto es desde VB.Net utiliza el signo igual única no sólo para la asignación, sino también para la comparación de igualdad, y así tratar de hacer

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

será interpretado como una comparación booleana de la s.AA-valor y la It.IsAny (Of String)(), invocando así al getter, que de nuevo dará como resultado un error de compilación. En su lugar, desea utilizar un Sub lambda (o posiblemente una función múltiple de línea lambda).

Si tiene un captador en la propiedad, sin embargo, una función lambda seguirá funcionando.

Cuestiones relacionadas