Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 Unit test NSubstitute Could not find a call to return from

I have a MVC4 web application I'm unit testing right now. It uses entity framework for the database portion. I'm using NSubstitute to mock the database. This code is basically copied and pasted from another site which works fine, so I hope I'm just missing something super simple.

Thanks in advance!

Applications table in SQL:

AppID   | ApplicationName
----------------------------
1       | MyCoolApplication
2       | MyOtherApplication

Entity created the Application class:

public class Application
{
    public int AppID { get; set; }
    public string ApplicationName { get; set; }
}

The mock section of the unit test looks like this:

var mockDb = Substitute.For<MyCoolApplicationsEntities>();

var applications = new List<Application>
{
    new Application {AppID = 1, ApplicationName = "MyCoolApplication"},
    new Application {AppID = 2, ApplicationName = "MyOtherApplication"},
};

var mockApplicationSet = Substitute.For<IDbSet<Application>, DbSet<Application>>();
mockApplicationSet.Provider.Returns(applications.AsQueryable().Provider);
mockApplicationSet.Expression.Returns(applications.AsQueryable().Expression);
mockApplicationSet.ElementType.Returns(applications.AsQueryable().ElementType);
mockApplicationSet.GetEnumerator().Returns(applications.AsQueryable().GetEnumerator());

mockApplicationSet.When(q => q.Add(Arg.Any<Application>()))
    .Do(q => applications.Add(q.Arg<Application>()));

mockApplicationSet.When(q => q.Remove(Arg.Any<Application>()))
    .Do(q => applications.Remove(q.Arg<Application>()));


mockDb.Applications.Returns(mockApplicationSet); //This is the line creating the error

The full error is:

Test method MyProjectName.Controllers.MyControllerTest.TestOfSectionImTesting threw exception: NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException: Could not find a call to return from.

Make sure you called Returns() after calling your substitute (for example: mySub.SomeMethod().Returns(value)), and that you are not configuring other substitutes within Returns() (for example, avoid this: mySub.SomeMethod().Returns(ConfigOtherSub())).

If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member. Return values cannot be configured for non-virtual/non-abstract members.

Correct use:

mySub.SomeMethod().Returns(returnValue);

Potentially problematic use:

mySub.SomeMethod().Returns(ConfigOtherSub());

Instead try:

var returnValue = ConfigOtherSub(); 

mySub.SomeMethod().Returns(returnValue);

But that doesn't work in my environment because Applications isn't a method. Like I said, this works fine in another site of mine, so it's got to be something basic I'm missing. Nothing I've found online has been helpful with my particular case. I updated to the newest version of NSubstitute and I uninstalled/reinstalled, but still have got nothing.

Again, thanks in advance!

like image 923
Timothy Avatar asked Dec 01 '22 18:12

Timothy


1 Answers

NSubstitute can not mock non-virtual members. (There are quite a few caveats to substituting for classes.)

MyCoolApplicationsEntities.Applications will need to be virtual for .Returns() to work.

like image 111
David Tchepak Avatar answered Dec 04 '22 10:12

David Tchepak