code首先"具有EF4&QUOT单元测试;和库 [英] Unit testing with EF4 "Code First" and Repository

查看:74
本文介绍了code首先"具有EF4&QUOT单元测试;和库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图得到一个单元测试手柄一个非常简单的ASP.NET MVC应用程序的测试我使用了最新EF4 CTP的code第一种方法建造。我不是很经验与单元测试/嘲讽等。

I am attempting to get a handle on Unit testing a very simple ASP.NET MVC test app I've built using the Code First approach in the latest EF4 CTP. I'm not very experience with Unit testing / mocking etc.

这是我的仓库类:

public class WeightTrackerRepository
{
    public WeightTrackerRepository()
    {
        _context = new WeightTrackerContext();
    }

    public WeightTrackerRepository(IWeightTrackerContext context)
    {
        _context = context;
    }

    IWeightTrackerContext _context;

    public List<WeightEntry> GetAllWeightEntries()
    {
        return _context.WeightEntries.ToList();
    }

    public WeightEntry AddWeightEntry(WeightEntry entry)
    {
        _context.WeightEntries.Add(entry);
        _context.SaveChanges();
        return entry;
    }
}

这是IWeightTrackerContext

This is IWeightTrackerContext

public interface IWeightTrackerContext
{
    DbSet<WeightEntry> WeightEntries { get; set; }
    int SaveChanges();
}

...及其实施,WeightTrackerContext

...and its implementation, WeightTrackerContext

public class WeightTrackerContext : DbContext, IWeightTrackerContext
{
    public DbSet<WeightEntry> WeightEntries { get; set; }
}

在我的测试中,我有以下几点:

In my test, I have the following:

[TestMethod]
public void Get_All_Weight_Entries_Returns_All_Weight_Entries()
{
    // Arrange
    WeightTrackerRepository repos = new WeightTrackerRepository(new MockWeightTrackerContext());

    // Act
    List<WeightEntry> entries = repos.GetAllWeightEntries();

    // Assert
    Assert.AreEqual(5, entries.Count);
}

和我MockWeightTrackerContext:

And my MockWeightTrackerContext:

class MockWeightTrackerContext : IWeightTrackerContext
{
    public MockWeightTrackerContext()
    {
        WeightEntries = new DbSet<WeightEntry>();
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("01/06/2010"), Id = 1, WeightInGrams = 11200 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("08/06/2010"), Id = 2, WeightInGrams = 11150 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("15/06/2010"), Id = 3, WeightInGrams = 11120 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("22/06/2010"), Id = 4, WeightInGrams = 11100 });
        WeightEntries.Add(new WeightEntry() { Date = DateTime.Parse("29/06/2010"), Id = 5, WeightInGrams = 11080 });
    }

    public DbSet<WeightEntry> WeightEntries { get;set; }

    public int SaveChanges()
    {
        throw new NotImplementedException();
    }
}

&GT;

当我试图建立一些测试数据,我不能创建一个 DbSet&LT出现我的问题,因为它没有构造函数。我得到我找错了树,我的整个方法试图模仿我的上下文的感觉。任何意见将是最欢迎这个完整的单元测试的新手。

My problem occurs when I'm trying to build up some test data as I can't create a DbSet<> as it has no constructor. I get the feeling I'm barking up the wrong tree with my whole approach trying to mock my context. Any advice would be most welcome to this complete unit testing newbie.

推荐答案

您通过工厂方法set()的环境中创建一个DbSet,但你不希望在你的单元测试的EF任何依赖。因此,你需要看看做什么实现使用IDbSet界面或使用嘲讽框架,如Moq的或RhinoMock之一的存根DbSet的存根。假设你写你自己的存根你刚才添加的WeightEntry对象到内部HashSet的。

You create a DbSet through the Factory method Set() on the Context but you don't want any dependency on EF in your unit test. Therefore, what you need to look at doing is implementing a stub of DbSet using the IDbSet interface or a Stub using one of the Mocking frameworks such as Moq or RhinoMock. Assuming you wrote your own Stub you'd just add the WeightEntry objects to an internal hashset.

如果您搜索对象集和IObjectSet你可能有更多的运气学习单元测试EF。这些都是之前的code首先CTP发布DbSet的同行有更多的写关于他们从单元测试的角度来看。

You may have more luck learning about unit testing EF if you search for ObjectSet and IObjectSet. These are the counterparts to DbSet prior to the code first CTP release and have a lot more written about them from a unit testing perspective.

下面是MSDN上,讨论EF code的可测性的优秀文章。它采用IObjectSet,但我认为它仍然是相关的。

Here's an excellent article on MSDN that discusses testability of EF code. It uses IObjectSet but I think it's still relevant.

至于大卫的评论的回应,我添加以下,因为这将不适合在-comments本增补。不知道这是长注释反应的最佳实践?

As a response to David's comment I'm adding this addendum below as it wouldn't fit in the -comments. Not sure if this is the best practice for long comment responses?

您应该改变IWeightTrackerContext接口从WeightEntries属性,而不是一个DbSet具体类型返回IDbSet。然后,您可以创建一个MockContext要么带着嘲弄的框架(推荐)或自定义的存根。这将从WeightEntries属性返回StubDbSet。

You should change the IWeightTrackerContext interface to return an IDbSet from the WeightEntries property rather than a DbSet concrete type. You can then create a MockContext either with a mocking framework (recommended) or your own custom stub. This would return a StubDbSet from the WeightEntries property.

现在你也将有code(即自定义库)依赖于IWeightTrackerContext其生产环境中,会通过你的实体框架WeightTrackerContext将实现IWeightTrackerContext。这往往是使用IoC框架通过构造函数注入完成,如统一。为了测试库code,它取决于你的EF会通过在实现MockContext所以在测试中的code认为它是聊到真正的EF数据库和行为(希望)如预期。正如你已经删除了多变的外部数据库系统和EF的依赖关系则可以可靠地验证您的单元测试库调用。

Now you will also have code (i.e Custom Repositories) that depend on the IWeightTrackerContext which in production you would pass in your Entity Framework WeightTrackerContext that would implement IWeightTrackerContext. This tends to be done through constructor injection using an IoC framework such as Unity. For testing the repository code that depends on EF you would pass in your MockContext implementation so the code under test thinks it's talking to the "real" EF and database and behaves (hopefully) as expected. As you have removed the dependancy on the changeable external db system and EF you can then reliably verify repository calls in your unit tests.

嘲讽框架的一个重要组成部分是提供给验证模拟对象的调用,以测试行为的能力。在你的榜样,您的测试上面实际上只测试DbSet添加功能,这不应该是你的问题,因为MS将有单元测试。你会想知道的是,到添加上DbSet的电话是从你自己的仓库code。如果合适内进行,这是那里的模拟框架进来了。

A big part of the mocking frameworks is providing the ability to verify calls on Mock objects to test behaviour. In your example above your test is actually only testing the DbSet Add functionality which shouldn't be your concern as MS will have unit tests for that. What you'd want to know is that the call to the Add on DbSet was made from within your own repository code if appropriate and that is where the Mock frameworks come in.

抱歉,我知道这是很多来消化,但如果你通过这篇文章有一个读了很多将变得更加清晰斯科特·艾伦在解释这个东西好了很多,比我:)

Sorry I know this is a lot to digest but if you have a read through that article a lot will become clearer as Scott Allen is a lot better at explaining this stuff than I am :)

这篇关于code首先&QUOT;具有EF4&QUOT单元测试;和库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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