Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nsubstitute, changing the value of a property which is substituted

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
}
like image 987
Pawel Maga Avatar asked Nov 29 '25 11:11

Pawel Maga


1 Answers

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...

like image 70
forsvarir Avatar answered Dec 01 '25 00:12

forsvarir



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!