Chris Marisic
Chris Marisic

Reputation: 33098

Moq how to correctly mock set only properties

What is the correct way for dealing with interfaces the expose set-only properties with Moq? Previously I've added the other accessor but this has bled into my domain too far with random throw new NotImplementedException() statements throughout.

I just want to do something simple like:

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

But this yields a compile error of The property 'SetOnlyValue' has no getter

Upvotes: 14

Views: 10167

Answers (2)

Ulf Åkerstedt
Ulf Åkerstedt

Reputation: 3236

Thanks Ruben!

And to help someone with a VB.Net gotcha this is the same code in 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 here is that you can't use a single-line Function lambda since this will be interpreted as an expression that returns a value, rather than the assignment statement that you are after. This is since VB.Net uses the single equal sign not only for assignment but also for equality comparison, and so trying to do

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

will be interpreted as a boolean comparison of the s.AA-value and the It.IsAny(Of String)(), thus invoking the getter, which will again result in a compile error. Instead you want to use a Sub lambda (or possibly a multi-line Function lambda).

If you have a getter on the property, however, a Function lambda will still work.

Upvotes: 3

Ruben Bartelink
Ruben Bartelink

Reputation: 61795

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" );
    }
}

Upvotes: 18

Related Questions