简体   繁体   English

单元测试服务层和实体框架6

[英]Unit Testing Service Layer and Entity Framework 6

I am just starting unit testing, so forgive me if this is an obvious answer. 我刚刚开始单元测试,所以如果这是一个明显的答案,请原谅我。

First, i do not have a repository layer, as i dont think an abstraction over Entity Framework is needed, so i have a project that contains my DbContext, then my service layer calls this. 首先,我没有存储库层,因为我认为不需要对Entity Framework进行抽象,所以我有一个包含我的DbContext的项目,然后我的服务层将其称为。

I am trying to build unit tests for my service layer and had lots of problems so far, but nearly there. 我正在尝试为我的服务层构建单元测试,到目前为止有很多问题,但是几乎在那里。 So far i have this 到目前为止,我有这个

[TestClass]
public class PageServiceTests
{
    private Mock<DbSet<Page>> _mockSet;
    private Mock<IDataContext> _mockContext;
    private PageService _service;

    [TestInitialize]
    public void TestInitialize()
    {
        var data = new List<Page>
        {
            new Page { Id = 1, Name = "Page1" },
            new Page { Id = 2, Name = "Page2", IsHomePage = true },
            new Page { Id = 3, Name = "Page3" }
        }.AsQueryable();

        _mockSet = data.MockSet<Page>();

        _mockContext = new Mock<IDataContext>();
        _mockContext.Setup(e => e.IsDetached(It.IsAny<Page>())).Returns(true);
        _mockContext.Setup(e => e.Pages).Returns(_mockSet.Object);
        _mockContext.Setup(e => e.Set<Page>()).Returns(_mockSet.Object);

        _service = new PageService(_mockContext.Object);
    }

    [TestMethod]
    public void GetAllAsync()
    {
        var pages = _service.GetAllAsync().Result;

        Assert.AreEqual(3, pages.Count);
        Assert.AreEqual("Page1", pages.ElementAt(0).Name);
        Assert.AreEqual("Page2", pages.ElementAt(1).Name);
        Assert.AreEqual("Page3", pages.ElementAt(2).Name);
    }

    [TestMethod]
    public void GetHomePageAsync()
    {
        var page = _service.GetHomeAsync().Result;

        Assert.AreEqual("Page2", page.Name);
    }

    [TestMethod]
    public void GetAsync()
    {
        var page = _service.GetAsync(2).Result;

        Assert.AreEqual("Page2", page.Name);
    }

    [TestMethod]
    public void AddAsync()
    {
        var page = new Page
        {
            Name = "New Page",
            IsHomePage = true,
            Index = 1
        };

        var result = _service.AddAsync(page).Result;

        _mockSet.Verify(m => m.Add(It.IsAny<Page>()), Times.Once);
        _mockContext.Verify(m => m.SaveChangesAsync(), Times.Once);
    }
}

Now this all seems to work, but i thought that a test to add a page should look something like this 现在这一切似乎都有效,但是我认为添加页面的测试应如下所示

[TestMethod]
public void AddAsync()
{
    var page = new Page
    {
        Name = "New Page",
        IsHomePage = true,
        Index = 1
    };

    var result = _service.AddAsync(page).Result;

    var pages = _service.GetAllAsync().Result;

    Assert.AreEqual(4, pages.Count);
}

But when i do this, i get a fail because pages only contains 3 records and not 4. I guess that i am not "mocking" the Add method in my service to add the page to DbSet. 但是,当我这样做时,我会失败,因为页面仅包含3条记录而不包含4条记录。我想我不是在“模拟”服务中的Add方法以将页面添加到DbSet中。 How do you do this, and is this a better way of doing it, or is what i have the "way" it should be done? 您如何做到这一点,这是一种更好的方法,还是我应该采取的“方法”?

Would it be bad practice to test this against the database directly? 直接针对数据库进行测试是否是错误的做法? It seems like i am jumping through hoops just to get the mocking framework to work with entity framework.. 似乎我只是为了使模拟框架与实体框架一起使用而跳了圈。

With your unit tests, you are testing Linq to Objects, not Linq to Entities. 通过单元测试,您正在测试Linq to Object,而不是Linq to Entities。 This, sometimes is a big difference and still can result in runtime errors if you're not querying a real database. 有时这是一个很大的差异,如果您不查询真实的数据库,仍然会导致运行时错误。

For a long time, I did the same... testing my repositories against mocked DbSets seemed as a good practice to me. 很长一段时间,我都做过同样的事情……对模拟的DbSet测试我的存储库对我来说似乎是一个好习惯。 But not anymore. 但现在不再。 Today it is very easy to create a test database at runtime with code first. 今天,使用代码优先在运行时创建测试数据库非常容易。 Of course, you need to prepare some sample data. 当然,您需要准备一些样本数据。 But this is what you have to do anyway (In your case, setting up the mocks). 但这仍然是您必须要做的(在您的情况下,设置模拟)。

I am curious what other people will answer. 我很好奇其他人会回答。

For your method calls ending in Async , it doesn't look like it's really running async since I don't see that or the await modifiers being used. 对于以Async结尾的方法调用,由于我没有看到它或正在使用await修饰符,因此它看起来好像不是真正在运行async If you call the async call without awaiting it, you would probaby see 3 items in the database as the database add record operation could complete after that check. 如果不等待而调用异步调用,则可能会在数据库中看到3个项目,因为该检查之后数据库添加记录操作可以完成。 I think if you used synchronous methods, or decorated with async/await, your unit test would work fine. 我认为,如果您使用同步方法,或使用async / await装饰,则单元测试会正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM