abatishchev
abatishchev

Reputation: 100348

Moq property with protected setter

I want to Moq next object:

abstract class Foo
{
    public string Bar { get; protected set; }
}

so that new Mock<Foo>().Bar return "Blah".

How can I do that?


fooMock.SetupGet<string>(s => s.Bar).Returns("Blah");

throws

Failure: System.NotSupportedException : Invalid setup on a non-virtual member: s => s.Date

and

fooMock.Protected().SetupGet<string>("Bar").Returns("Blah");

throws

To specify a setup for public property StatementSection.Date, use the typed overloads

Upvotes: 11

Views: 6779

Answers (3)

gbro3n
gbro3n

Reputation: 6967

Here's an example of providing a proxy class that can modify the protected property via it's constructor (MyClass is proxied by MyClassProxy). Tests are XUnit.

public class MyClassEqualityComparerTests
{
    /// <summary>
    /// Normal class
    /// </summary>
    public class MyClass
    {
        public Guid Id { get; protected set; }
    }

    /// <summary>
    /// Proxy class facilitates setting of protected Id
    /// </summary>
    public class MyClassProxy : MyClass
    {
        public MyClassProxy(Guid id)
        {
            this.Id = id;
        }
    }

    public class MyClassEqualityComparer : IEqualityComparer<MyClass>
    {
        public bool Equals(MyClass x, MyClass y)
        {
            return x.Id.Equals(y.Id);
        }

        public int GetHashCode(MyClass obj)
        {
            return obj.Id.GetHashCode();
        }
    }

    [Fact]
    public void CompareSameMyClasss_ShouldBeEqual()
    {
        var sharedGuid = Guid.NewGuid();

        var myClass1 = new MyClassProxy(sharedGuid);
        var myClass2 = new MyClassProxy(sharedGuid);

        //arrange
        var myClassEqualityComparer = new MyClassEqualityComparer();

        //act
        bool equals = myClassEqualityComparer.Equals(myClass1, myClass2);

        //assert
        equals.Should().BeTrue();
    }

    [Fact]
    public void CompareDifferentMyClasss_ShouldNotBeEqual()
    {
        var myClass1 = new MyClassProxy(Guid.NewGuid());
        var myClass2 = new MyClassProxy(Guid.NewGuid());

        //arrange
        var myClassEqualityComparer = new MyClassEqualityComparer();

        //act
        bool equals = myClassEqualityComparer.Equals(myClass1, myClass2);

        //assert
        equals.Should().BeFalse();
    }
}

Upvotes: 1

John Foster
John Foster

Reputation: 8755

Like Felice (+1) said mocking creates a proxy which means you need to either make things virtual (so Moq can work its proxying magic and override the property).

As an alternative if you just want to squirt in a value you can manually stub the class you want to test and expose a means to get at the setter:-

public class FooStub : Foo {
    public SetBar(string newValue) {
       Bar = newValue;
    }
}

Upvotes: 10

Felice Pollano
Felice Pollano

Reputation: 33272

Since mocking is done by creating a proxy of your class,only virtual function/property can be "moqued"

Upvotes: 9

Related Questions