单元测试 DbContext [英] Unit Testing DbContext

查看:24
本文介绍了单元测试 DbContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我研究了一些有关可用于单元测试 DbContext 的技术的信息.我想向上下文添加一些内存数据,以便我的测试可以针对它运行.我正在使用数据库优先方法.

I've researched some information about techniques I could use to unit test a DbContext. I would like to add some in-memory data to the context so that my tests could run against it. I'm using Database-First approach.

我发现最有用的两篇文章是 thisthis.该方法依赖于创建 MyContext 和 FakeContext 都将实现的 IContext 接口,从而允许 Mock 上下文.

The two articles I've found most usefull were this and this. That approach relies on creating an IContext interface that both MyContext and FakeContext will implement, allowing to Mock the context.

但是,我试图避免使用存储库来抽象 EF,如 指出 作者 一些人,因为 EF 4.1 已经通过 DbSet 和 DbContext 实现了存储库和工作单元模式,我真的很想保留 EF 团队实现的所有功能,而不必自己使用通用存储库维护它们,如我已经在其他项目中做过了(这有点痛苦).

However, I'm trying to avoid using repositories to abstract EF, as pointed by some people, since EF 4.1 already implements repository and unit of work patterns through DbSet and DbContext, and I really would like to preserve all the features implemented by the EF Team without having to maintain them myself with a generic repository, as I already did in other project (and it was kind of painful).

使用 IContext 会让我走上同样的道路(或者不会?).

Working with an IContext will lead me to the same path (or won't it?).

我考虑过创建一个从主 MyContext 继承的 FakeContext,从而利用它下面的 DbContext 来运行我的测试,而无需访问数据库.我找不到类似的实现,所以我希望有人可以帮助我.

I thought about creating a FakeContext that inherits from main MyContext and thus take advantage of the DbContext underneath it to run my tests without hitting the database. I couldn't find similar implementations, so I'm hoping someone can help me on this.

我是不是做错了什么,或者这会导致我遇到一些我没有预料到的问题吗?

推荐答案

问自己一个问题:你要测试什么?

Ask yourself a single question: What are you going to test?

您提到了 FakeContext 和 Mocking the context - 为什么要同时使用两者?这些只是做同样事情的不同方法 - 仅提供上下文的测试实现.

You mentioned FakeContext and Mocking the context - why to use both? Those are just different ways to do the same - provide test only implementation of the context.

还有一个更大的问题 - 伪造或模拟上下文或集合只有一个结果:您不再测试真正的代码.

There is one more bigger problem - faking or mocking context or set has only one result: You are not testing your real code any more.

简单例子:

public interface IContext : IDisposable
{
    IDbSet<MyEntity> MyEntities { get; }
}

public class MyEntity
{
    public int Id { get; set; }
    public string Path { get; set; } 
}

public class MyService
{
    private bool MyVerySpecialNetMethod(e)
    {
        return File.Exists(e.Path);
    }

    public IEnumerable<MyEntity> GetMyEntities()
    {
        using (IContext context = CreateContext())
        { 
            return context.MyEntities
                .Where(e => MyVerySpecialNetMethod(e))
                .Select(e)
                .ToList();
        }
    }
}

现在假设您的 SUT 中有这个(被测系统 - 在单元测试的情况下,它是一个单元 = 通常是一个方法).在测试代​​码中,您提供 FakeContextFakeSet 并且它会起作用 - 您将进行绿色测试.现在在生产代码中,您将提供另一个派生的 DbContextDbSet,您将在运行时遇到异常.

Now imagine that you have this in your SUT (system under test - in case of unit test it is an unit = usually a method). In the test code you provide FakeContext and FakeSet and it will work - you will have a green test. Now in the production code you will provide a another derived DbContext and DbSet and you will get exception at runtime.

为什么?因为通过使用 FakeContext,您还更改了 LINQ 提供程序,并且您运行的是 LINQ to Objects 而不是 LINQ to Entities,因此调用无法转换为 SQL 的本地 .NET 方法以及许多其他 LINQ 功能在 LINQ to Entities 中不可用!您还可以通过数据修改发现其他问题 - 参照完整性、级联删除等.这就是为什么我认为处理上下文/LINQ to Entities 的代码应该包含在集成测试中并针对真实数据库执行的原因.

Why? Because by using FakeContext you have also changed LINQ provider and instead of LINQ to Entities you are running LINQ to Objects so calling local .NET methods which cannot be converted to SQL works as well as many other LINQ features which are not available in LINQ to Entities! There are other issues you can find with data modification as well - referential integrity, cascade deletes, etc. That is the reason why I believe that code dealing with context / LINQ to Entities should be covered with integration tests and executed against the real database.

这篇关于单元测试 DbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆