Mocking a Collection ClusterState

1

I am trying to mock the cluster state of a mongo collection so it gives back a ClusterState.Connected. Below you will see one of my unit tests. Currently this is giving back an error, is there any way to Mock the Collection.Database.Client.Cluster.Description.State?

[Fact]
public void HealthCheck_SucceededDatabase_Connection()
{

    //Arrange
    var myRepository = new Mock<IRepository<RepoEntityObject>>();
    var healthCheck = new HealthCheck(myRepository.Object);

    //Setup
    myRepository.Setup(mcr => mcr.Collection.Database.Client.Cluster.Description.State).Returns(ClusterState.Connected);

    //Act
    var result = healthCheck.ExecuteHealthchecks();

    //Results
    result[0].CheckType.ShouldBe("Service is alive");
    result[0].Message.ShouldBe("");
    result[0].Passed.ShouldBe(true);

    result[1].CheckType.ShouldBe("MongoDB");
    result[1].Message.ShouldBe("Service is alive");
    result[1].Passed.ShouldBe(True);
}

Error Stack Trace:

System.NotSupportedException occurred HResult=0x80131515
Message=Invalid setup on a non-virtual (overridable in VB) member: mcr => mcr.Collection.Database.Client.Cluster.Description.State Source= StackTrace: at Moq.Mock.ThrowIfSetupExpressionInvolvesUnsupportedMember(Expression setup, MethodInfo method) at Moq.Mock.<>c__DisplayClass62_0`2.b__0() at Test.Unit.HealthCheckTests.HealthCheck_SucceededDatabase_Connection() in C:\HealthCheckTests.cs:line 50

Edit One Possible solution:

Making the Description.State attribute virtual is not something I am trying to implement since this method is coming from the MongoDb C# driver that I am using and I am not looking into overriding it.

enter image description here

c#
mongodb
unit-testing
moq
asked on Stack Overflow Aug 18, 2017 by Lostaunaum • edited Jul 19, 2019 by Nkosi

1 Answer

2

This is the key phrase Invalid setup on a non-virtual member. Make the property virtual. otherwise if unable to because you are not in control of said property then encapsulate the desired property and expose it as virtual

public interface IRepository<T> {
    ClusterState State { get; }
    //...other members removed for brevity
}

Now you can mock the member you control

//Arrange
var myRepository = new Mock<IRepository<RepoEntityObject>>();
var healthCheck = new HealthCheck(myRepository.Object);

//Setup
myRepository.Setup(mcr => mcr.State).Returns(ClusterState.Connected);

//...code removed for brevity

Now with that said, you have now realized that your repository is leaking implementation concerns that are difficult to mock in isolation. Consider reviewing your design choices regarding your level of abstractions.

answered on Stack Overflow Aug 18, 2017 by Nkosi

User contributions licensed under CC BY-SA 3.0