【问题标题】:NSubstitute throws CouldNotSetReturnDueToTypeMismatchException when mocking Query on NHibernate SessionNSubstitute 在 NHibernate Session 上模拟查询时抛出 CouldNotSetReturnDueToTypeMismatchException
【发布时间】:2014-11-09 18:36:20
【问题描述】:

我有一个提供 GetAll 方法的存储库,该方法再次调用 NHibernate 的 ISession 实例上的 Query 扩展方法。

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

我的单元测试如下所示:

[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>();
}

在_fixture.Session.Query().Returns(productList)语句中,NSubstitute抛出如下异常:

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

由于 Query 是扩展方法,NSubstitute 似乎无法设置返回值。我将如何模拟 ISession 上的扩展方法调用?

【问题讨论】:

标签: nhibernate extension-methods iqueryable nsubstitute


【解决方案1】:

最简单的解决方案是将你的 ISession 包装在另一个接口/具体类中,这样你就可以把它存根:

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

【讨论】:

    【解决方案2】:

    没有办法用 NSubstitute 模拟扩展方法,但是如果你知道里面使用的是什么扩展方法,那么你可以模拟它。您的测试将在模拟对象上使用扩展方法,最终它将使用模拟方法。困难的部分是知道里面发生了什么。

    它在项目中对我有用,我知道所有的源代码,我可以检查里面的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 2017-05-17
      相关资源
      最近更新 更多