Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq how to correctly mock set only properties

Tags:

c#

.net

moq

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

like image 270
Chris Marisic Avatar asked May 17 '10 22:05

Chris Marisic


People also ask

How do I mock a read only property?

you can set up Foo (a read-only property) like this: var stub = new Mock<MyAbstraction>(); stub. SetupGet(x => x. Foo).

How do you mock a method in MOQ?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.


2 Answers

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" );
    }
}
like image 54
Ruben Bartelink Avatar answered Sep 23 '22 21:09

Ruben Bartelink


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.

like image 31
Ulf Åkerstedt Avatar answered Sep 25 '22 21:09

Ulf Åkerstedt