NSubstitute throws CouldNotSetReturnDueToTypeMismatchException on ridiculous request on NHibernate session

I have a repository offering a GetAll method that calls the request extension method again on the ISession NHibernate instance.

public ICollection<Product> GetAll()
{
    return _session.Query<Product>().ToList();
}

      

My unit test looks like this:

[Test]
public void GetAllReturnsCollectionFromSession()
{
    IQueryable<Product> productList = new ProductListBuilder().Build().AsQueryable();

    _fixture.Session.Query<Product>().Returns(productList);

    var sut = _fixture.CreateSut();

    var result = sut.GetAll();

    Assert.AreSame(productList, result);

    _fixture.Session.Received().Query<Product>();
}

      

In the _fixture.Session.Query () statement. Returns (productList), NSubstitute throws the following exception:

NSubstitute.Exceptions.CouldNotSetReturnDueToTypeMismatchException : Can not return value of type IQueryable`1Proxy for ISession.GetSessionImplementation (expected type ISessionImplementor).

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);

   at NSubstitute.Core.ConfigureCall.CheckResultIsCompatibleWithCall(IReturn valueToReturn, ICallSpecification spec)
   at NSubstitute.Core.ConfigureCall.SetResultForLastCall(IReturn valueToReturn, MatchArgs matchArgs)
   at NSubstitute.Core.CallRouter.LastCallShouldReturn(IReturn returnValue, MatchArgs matchArgs)
   at NSubstitute.Core.SubstitutionContext.LastCallShouldReturn(IReturn value, MatchArgs matchArgs)
   at NSubstitute.SubstituteExtensions.Returns[T](MatchArgs matchArgs, T returnThis, T[] returnThese)
   at NSubstitute.SubstituteExtensions.ReturnsForAnyArgs[T](T value, T returnThis, T[] returnThese)
   at Statoil.Wellcom.DataLayer.Implementation.Oracle.UnitTests.Repositories.DwapplicationRepositoryTests.GetAllReturnsCollectionFromSession() in C:\git\WELLCOM\source\Statoil.Wellcom.DataLayer.Implementation.Oracle.UnitTests\Repositories\DwapplicationRepositoryTests.cs:line 123

      

It looks like NSubstitute is unable to set the return value due to Query being an extension method. How could I make fun of calling an extension method on an ISession?

+3


source to share


2 answers


The simplest solution is to wrap your ISession in another interface / concrete class so you can disable it:



public interface ISessionWrapper 
{
    IQueryable<T> Query<T>();
}

public class SessionWrapper : ISessionWrapper
{
    private readonly ISession _session;

    public SessionWrapper(ISession session)
    {
        _session = session;
    }

    public IQueryable<T> Query<T>()
    {
        return _session.Query<T>();
    }
}

      

+1


source


There is no way to wash the extension method with NSubstitute, however if you know which extension method is using internally than you can scoff at that. Your test will use the extension method on the mocked object, and it will end up using the mock method. The hard part is knowing what's going on inside.



It worked for me on projects where I knew all the source code and I could check what's inside.

0


source







All Articles