【问题标题】:How do you shim FirstOrDefault in EntityFramework?您如何在 EntityFramework 中填充 FirstOrDefault?
【发布时间】:2013-11-03 14:42:05
【问题描述】:

使用 Microsoft Fakes 和 Entityframework,我正在尝试为 FirstOrDefault() 创建一个 shim。我有一个方法要进行单元测试,如下所示:

protected override v_Titles GetEntityByKey(Guid key)
    {
        var result = Context.v_Titles.FirstOrDefault(t => t.Id == key);
        if ( result == null )
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
        return result;
    }

由公共方法 Get(Guid key) 调用。

我设置了 fakes 并填充了数据库和 v_Titles 集合:

public void SetUp()
    {
        _titles = new List<v_Titles>
        {
            new v_Titles
            {
                Id = new Guid(1,0,0,0,0,0,0,0,0,0,0),
                PostedDate = new DateTime(2013,1,1),
                Title = "2013-01-01"
            },
            new v_Titles
            {
                Id = new Guid(2,0,0,0,0,0,0,0,0,0,0),
                PostedDate = new DateTime(2013,5,23),
                Title = "2013-05-23"
            },
            new v_Titles
            {
                Id = new Guid(3,0,0,0,0,0,0,0,0,0,0),
                PostedDate = new DateTime(2013,8,10),
                Title = "2013-08-10"
            }
        };


        _shimTitles = new ShimDbSet<v_Titles>();
        _shimTitles.Bind(_titles);

        ...

        _databaseShim = new shimDatabaseEntities();
        _databaseShim.v_TitlesGet = () => _shimTitles.Instance;

        _target = new TitlesController
        {
            Context = _databaseShim.Instance
        };

进一步的...在哪里我已经尝试了以下垫片来让 FirstOrDefault 工作:

            System.Linq.Fakes.ShimEnumerableQuery<v_Titles>.AllInstances.GetEnumerator = (a) =>
            { return _titles.GetEnumerator(); };
        System.Linq.Fakes.ShimQueryable.FirstOrDefaultOf1IQueryableOfM0<v_Titles>((a) =>
            {
                return _titles.FirstOrDefault();
            });
        databaseEntities.AllInstances.v_TitlesGet = (a) => _shimTitles.Instance;

我的单元测试如下所示:

        [TestMethod]
    public void Get_ReturnsOneItem_Test()
    {
        using (ShimsContext.Create())
        {
            var expected = new Guid(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
            SetUp();
            var result = _target.Get(expected);
        }
    }

运行测试时,我在 .FirstOrDefault() 调用中遇到以下异常。

System.ArgumentNullException 未被用户代码处理 H结果=-2147467261 Message=Value 不能为空。 参数名称:arguments 源=System.Core 参数名称=参数 堆栈跟踪: 在 System.Linq.Expressions.Expression.RequiresCanRead(表达式表达式,字符串参数名称) 在 System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase 方法,ExpressionType nodeKind,Expression arg,ParameterInfo pi) 在 System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase 方法,ExpressionType nodeKind,ReadOnlyCollection1& arguments) at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable1 参数) 在 System.Linq.Expressions.Expression.Call(表达式实例,MethodInfo 方法,表达式 [] 参数) 在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable1 source, Expression1 谓词) 在 Controllers\Api\TitlesController.cs:line 42 中的 WebSite.Web.Controllers.Api.TitlesController.GetEntityByKey(Guid key) 在 System.Web.Http.OData.EntitySetController`2.Get(TKey 键) 在 TitlesController_Tests.cs:line 96 中的 WebSite.Web.Tests.TitlesController_Tests.Get_ReturnsOneItem_Test() 内部异常:

如何让 FirstOrDefault 返回一些东西?它甚至不必执行查询,我只想测试我正在调用 FirstOrDefault 并返回它返回的值或在返回 null 时引发异常。

【问题讨论】:

  • 我认为你试图模拟 EntityFramework 是对的吗?
  • 这似乎不对。您想模拟 Context.v_Titles 部分,而不是 Linq/EF 部分。接下来是“如何模拟System.String
  • 我确实模拟了 Context.v_Titles,如我的代码所示。我将 v_Titles 绑定到一个集合,并在查看 Context.v_Titles 时返回该集合。它只会在 FirstOrDefault() 调用时爆炸。
  • 同意@HenkHolterman。这也是我不喜欢 Fakes 框架的原因之一。它迫使你做这些事情。您不会想对 FirstOrDefault() 进行存根。该 API 是 Linq 的一部分,并且经过了很好的测试。因此,您可以假设它始终提供给定集合中的 FirstOrDefault。集合/上一级是您应该存根的集合。
  • @Raj:假货绝不会强迫你做这样的事情。这是你一开始就不应该做的事情。在这段代码中,我没有看到存根,这可能意味着完全没有 DI,导致需要 shims。因为看起来他只是简单地包装了 EF,并隐藏了它背后的机制,所以这并不真正符合单元测试的条件——它与 DI 完全相反。

标签: c# entity-framework unit-testing microsoft-fakes


【解决方案1】:

阅读您的帖子,我认为我遇到了同样的问题,我不会复制并粘贴我找到并为我工作的解决方案,而是给您网址:

http://mylifeandcode.blogspot.com/2012/10/unit-testing-with-mock-entity-framework.html

玩得开心!!!

【讨论】:

  • 虽然此链接可能会回答问题,但您应避免仅提供链接的答案。
  • 复制和粘贴实际上并没有那么糟糕,然后提供您的链接和站点名称作为来源。然而,用你自己的话表达一些东西并将其专门应用于问题会明显更好。有关详细信息,请参阅How to Answer。谢谢!
  • 投反对票,因为这个问题是针对微软假货提出的
猜你喜欢
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 2015-04-25
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多