203

I'm new to Moq. I'm mocking a PagingOptions class. Here is how the class looks like:

public class PagingOptions
    {
        [Range(1, 99999, ErrorMessage = "Offset must be greater than 0.")]
        public int? Offset { get; set; }

        [Range(1, 100, ErrorMessage = "Limit must be greater than 0 and less than 100.")]
        public int? Limit { get; set; }

        public PagingOptions Replace(PagingOptions newer)
        {
            return new PagingOptions
            {
                Offset = newer.Offset ?? Offset,
                Limit = newer.Limit ?? Limit
            };
        }
    }

Here is my mock version of the class,

var mockPagingOptions = new Mock<PagingOptions>();
            mockPagingOptions.Setup(po => po.Limit).Returns(25);
            mockPagingOptions.Setup(po => po.Offset).Returns(0);

I get the below error when setting up the property values. Am I making something wrong. Looks like I cannot Moq concrete class? Only Interfaces can be Mocked? Please assist.

moq error

Thanks, Abdul

5
  • 8
    Make the properties Offset and Limit virtual. learn.microsoft.com/en-us/dotnet/csharp/language-reference/… Commented Jul 5, 2019 at 15:18
  • 12
    In this case it doesn't seem like there's a reason to mock this. You can just create an actual instance of PagingOptions and set its properties instead of using a Mock. Don't make anything virtual. Commented Jul 5, 2019 at 15:18
  • 3
    unless this is an XY problem I see no need to mock this object. There appears to be no obvious knock on effects of using the object as is that would warrant having to create a mock Commented Jul 5, 2019 at 15:22
  • @ScottHannen How to find which object to mock and which not to mock? how are you differentiating? Commented Jul 5, 2019 at 15:25
  • 1
    @AbdulRahman stackoverflow.com/a/38256/5233410 Commented Jul 5, 2019 at 15:30

7 Answers 7

268

Moq creates an implementation of the mocked type. If the type is an interface, it creates a class that implements the interface. If the type is a class, it creates an inherited class, and the members of that inherited class call the base class. But in order to do that it has to override the members. If a class has members that can't be overridden (they aren't virtual, abstract) then Moq can't override them to add its own behaviors.

In this case there's no need to mock PagingOptions because it's easy to use a real one. Instead of this:

var mockPagingOptions = new Mock<PagingOptions>();
mockPagingOptions.Setup(po => po.Limit).Returns(25);
mockPagingOptions.Setup(po => po.Offset).Returns(0);

Do this:

var pagingOptions = new PagingOptions { Limit = 25, Offset = 0 };

How do we determine whether or not to mock something? Generally speaking, we mock something if we don't want to include the concrete runtime implementation in our test. We want to test one class not both at the same time.

But in this case PagingOptions is just a class that holds some data. There's really no point in mocking it. It's just as easy to use the real thing.

Sign up to request clarification or add additional context in comments.

3 Comments

Although this works if these are the only properties/methods you want to test, it doesn't if you want to predict other properties/methods behavior in pagingOptions.
I don't agree with the approach that you can just use the real class. I believe that the only real class that should be created in the unit test is the class under the test, all it's dependencies should be mocked, does not matter if they are complex or not, developer shouldn't have to look inside the dependency class to assed if it should be mocked or not causes this will confuse others that follow and will see places where mocks are used and not. The rules must be simple and deterministic for others to follow them. Also what if the instance changes in time and creates file on the drive ?
Forced consistency for the sake of consistency is a root of evil. No one will be confused because someone used a mock where they needed one but not where they didn't need one. scotthannen.org/blog/2020/10/14/consistency.html
93

I had the same error, but in my case I was trying to mock the class itself and not its interface:

// Mock<SendMailBLL> sendMailBLLMock = new Mock<SendMailBLL>(); // Wrong, causes error.
Mock<ISendMailBLL> sendMailBLLMock = new Mock<ISendMailBLL>();  // This works.

sendMailBLLMock.Setup(x =>
    x.InsertEmailLog(
        It.IsAny<List<EmailRecipient>>(),
        It.IsAny<List<EmailAttachment>>(),
        It.IsAny<string>()));

5 Comments

That helps a lot. Thank you so much. In case you want to set some operation, obj.Setup(...).Returns(/*mock implementation*/); ref: stackoverflow.com/questions/41351543/…
As stupid as it seems, this was my problem as well. Helpful to double check if you are using the interface, before digging deeper what could possible have gone wrong.
I was having the same problem, many thanks for your valuable answer. It works for me using interface instead, exactly the way you have mentioned in the code block. Thumb sup.
This should be the actually accepted answer. It is considered a best practice to use interfaces when mocking inside of your unit tests, so that pieces can be removed and replaced flexibly. Also, it makes sense with what Moq is doing behind the scenes, creating a class that fits the defined interface and redefining the behavior of different class members.
I had to change a lot of my internal dependencies to have this implemented, but am very happy after doing that.. Code looks so much SOLID
23

In case you reached this question based on the original title Non-overridable members may not be used in setup / verification expressions and none of the other answers have helped you may want to see if reflection can satisfy your test needs.

Suppose you have a class Foo with a property defined as public int I { get; private set; }

If you try the various methods in the answers here few of them will work for this scenario. However you can use .net reflection to setup a value of an instance variable and still keep fairly good refactoring support in the code.

Here is a snippet that sets a property with a private setter:

var foo = new Foo();
var I = foo.GetType().GetProperty(nameof(Foo.I), BindingFlags.Public | BindingFlags.Instance);
I.SetValue(foo, 8675309);

I do not recommend this for production code. It has proven very useful in numerous tests for me. I found this approach a few years ago but needed to look it up again recently and this was the top search result.

Comments

16

I want to improve Scott's answer and give a general answer

If the type is a class, it creates an inherited class, and the members of that inherited class call the base class. But in order to do that it has to override the members. If a class has members that can't be overridden (they aren't virtual, abstract) then Moq can't override them to add its own behaviors.

In my situation i had to make the prop virtual. So answer to your class code is:

public class PagingOptions {
    [Range (1, 99999, ErrorMessage = "Offset must be greater than 0.")]
    public virtual int? Offset { get; set; }

    [Range (1, 100, ErrorMessage = "Limit must be greater than 0 and less than 100.")]
    public virtual int? Limit { get; set; }

    public PagingOptions Replace (PagingOptions newer) {
        return new PagingOptions {
            Offset = newer.Offset ?? Offset,
                Limit = newer.Limit ?? Limit
        };
    }
}

use same:

var mockPagingOptions = new Mock<PagingOptions>();
        mockPagingOptions.Setup(po => po.Limit).Returns(25);
        mockPagingOptions.Setup(po => po.Offset).Returns(0);

5 Comments

yes but now you're modifying a property accessor just for testability sake
yes but you have to if you want to mock it
Should be noted that official MS docs have the DbSet properties marked as virtual for this specific purpose: learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/…
You could modify a property accessor just for testability or add an interface just for testability. Which is more desireable depends on circumstance. I all the time mark things internal and "share internals to" just for testability...
Doesn't work if the class that you want to mock is external/unmanaged code.
5

In my case I was mocking a public method which was not virtual. Making the method virtual made the trick.

As an old Java developer, I'm used to the approach that all public methods are already virtual, there is no need to mark them separately as virtual so that sub classes can override them. C# is different here.

Maybe someone can explain if it is ok to mark a public method in a production code as virtual for testing purposes in C#.

Edit: I've come across the official EF Core documentation which recommends making DbSet properties of a DbContext virtual for testing, so maybe this is not a bad practice.

Comments

3

On occasion you may be working with a class from a third party library that has properties which can be directly set or mocked.

Where the answer by above is not sufficient you can also invoke the setter method directly, for example where a class has a property called "Id" with no accessible setter:

var idSetter = account.GetType().GetMethod("set_Id", BindingFlags.Instance | BindingFlags.NonPublic);

idSetter!.Invoke(account, new[] { "New ID Here" });

1 Comment

This is a great solution when you are trying to use 3rd-party libraries with private setters, but this definitely feels concerning that this is even possible. This worked to prevent us from needing to create fakes.
0

Late for the party, but I brought some tasty cake for those who are still hungry. I've found there's a specific SetupGet that allows you to mock getters. It does not require any code change on the class side.

var mockPagingOptions = new Mock<PagingOptions>();
mockPagingOptions.SetupGet(po => po.Limit).Returns(25);
mockPagingOptions.SetupGet(po => po.Offset).Returns(0);

There's also a SetupSet version, which takes care of the Setters.

3 Comments

i might be late, but please save some cake for me!
I like cake, but this cake still throws an unsupported exception: Non-overridable members (here: QueryResult.get_Items) may not be used in setup / verification expressions.
As was mentioned in the previous comment: this cannot be done unless those properties are virtual. If you are trying to mock external libraries, these .SetupGet calls won't work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.