[SOLVED] Make all EF Core model properties virtual for mocking in unit tests with Moq and xUnit?

Issue

I am using the repository pattern as suggested by the documentation for unit testing in EF Core. I have reached a point in my code where I am not able to fully test a method properly as a result of doing operations on the models from EF Core and not the DB Context.

An example of what I mean is below:

Code to be tested:

    private static void AddToUserScore(Members member)
    {
        var basePoints = 2;

        if (member.HintAsked)
        {
            basePoints--;
            member.HintAsked = false;
        }

        if (member.LocationHintAsked)
        {
            basePoints--;
            member.LocationHintAsked = false;
        }

        member.UserScore += basePoints;
    }

EF Core Context Model itself:

public class Members
{
    public int MemberId { get; set; }
    public int AppId { get; set; }
    public string Username { get; set; }
    public int UserScore { get; set; }
    public string QuestionIds { get; set; }
    public int CurrentQuestionNumber { get; set; }
    public int LocationId { get; set; }
    public bool HintAsked { get; set; }
    public bool LocationHintAsked { get; set; }
}

Unit test sample:

 var fakeMemberMock = Fixture.Create<Mock<Members>>();
 fakeMemberMock.SetupSet(members => members.HintAsked = false);
 fakeMemberMock.VerifyGet(members => members.HintAsked, Times.Exactly(1));

Since none of my model’s properties are virtual, this will result in an error at runtime.

I want to know if there is any reason I should not make my EF Core models all virtual for
this purpose.

I am not to sure of any sideffects this may have with interaction with my database or any pros and cons of doing this. I know virtual is generally placed on navigational properties but i do not know wether doing this on normal properties is a good idea or not.

Feel free to mention another method of going about what I am attempting that would be simpler.

Thanks in advance.

Solution

Let me ask, isn’t testing the internals of the method too granular? The alternative would be testing the method instead of the model class. The method does a unit of work which is testable.

// test case 1
var model1 = new Members();
model1.UserScore = 10;
model1.HintAsked = true;

// run the method AddToUserScore on model

// do the asserts
Assert.Equal(..., model1.UserScore);

// test case 2
var model1 = new Members();
model1.UserScore = 10;
model1.LocationHintAsked = true;

Answered By – Martin Staufcik

Answer Checked By – Robin (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *