Nsubstitute, changing the value of a property which is substituted

2.5k views Asked by At

I would like to mock a property in my model to a specific value (because it has a private setter). Then I would call a method which changing this property and then check result. The problem is that the property would always return this value. Can I somehow get around this problem?

Here is example:

public class Tests
{
    [Fact]
    public void Test1()
    {
        //Arrange
        var document = Substitute.For<Document>();
        document.State.Returns(DocumentState.Confirmed);

        //Act
        document.Close();

        //Assert
        Assert.Equal(DocumentState.Closed, document.State); // FAIL, State still equals "DocumentState.Confirmed"
    }
}

public class Document
{
    public virtual DocumentState State { get; private set; }

    public void Close()
    {
        if (State != DocumentState.Confirmed)
            throw new InvalidOperationException();

        State = DocumentState.Closed;
    }
}

public enum DocumentState
{
    Draft,
    Confirmed,
    Closed
}
1

There are 1 answers

2
forsvarir On BEST ANSWER

It's a really bad idea to Mock the class you're testing. It can lead to all sorts of weird issues, not to mention tightly coupled tests. If you really want to test this scenario, then you can hand-roll a testable stub:

public class TestableDocument : Document {
    DocumentState _state;
    bool first = true;
    public TestableDocument(DocumentState state) {
        _state = state;
    }
    public override DocumentState State {
        get {
            if (first) {
                first = false;
                return _state;
            }
            return base.State;
        }
    }
}

Then you'd instantiate that in your test, rather than a Document.

[Fact]
public void Test1()
{
    //Arrange
    var document = new TestableDocument(DocumentState.Confirmed));

    //Act
    document.Close();

    //Assert
    Assert.Equal(DocumentState.Closed, document.State); 
}

There may be a way of doing something similar with NSubstitute, but I don't know what it is.

Generally speaking though, if you're mocking the class you're testing then there's a good chance you're either testing the wrong thing or you should look at refactoring your code...