【问题标题】:Unit Testing Service Layer and Entity Framework 6单元测试服务层和实体框架 6
【发布时间】:2014-12-02 11:32:13
【问题描述】:

我刚刚开始单元测试,如果这是一个明显的答案,请原谅我。

首先,我没有存储库层,因为我认为不需要对实体框架进行抽象,所以我有一个包含我的 DbContext 的项目,然后我的服务层调用它。

我正在尝试为我的服务层构建单元测试,到目前为止遇到了很多问题,但几乎就在那里。到目前为止我有这个

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

现在这一切似乎都工作了,但我认为添加页面的测试应该看起来像这样

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

但是当我这样做时,我会失败,因为页面只包含 3 条记录而不是 4 条记录。我想我不是在“模拟”我的服务中的 Add 方法来将页面添加到 DbSet。你是怎么做到的,这是一种更好的方法,还是我有“方法”应该做的?

直接对数据库进行测试会是不好的做法吗?似乎我只是为了让模拟框架与实体框架一起工作而跳过箍..

【问题讨论】:

  • 我看到您决定使用测试数据库。您能否分享一下您为此编写的设置和测试作为您的答案?

标签: c# .net entity-framework unit-testing testing


【解决方案1】:

通过单元测试,您是在测试 Linq to Objects,而不是 Linq to Entities。这有时是一个很大的区别,如果您不查询真实数据库,仍然可能导致运行时错误。

很长一段时间以来,我都在做同样的事情...针对模拟的 DbSet 测试我的存储库对我来说似乎是一种好习惯。但现在不是了。今天,在运行时首先使用代码创建测试数据库非常容易。当然,您需要准备一些样本数据。但无论如何,这是你必须做的(在你的情况下,设置模拟)。

我很好奇其他人会怎么回答。

【讨论】:

  • 感谢您的回复。我一直想知道为什么不直接使用“测试”数据库。我认为这种嘲弄的东西本身就需要更多的工作,而且我确实想针对数据库测试我的代码。我想我会听取您的建议,放弃模拟并创建一个测试 sql 数据库。再次感谢
【解决方案2】:

对于以Async 结尾的方法调用,它看起来不像真的在运行async,因为我没有看到它或正在使用await 修饰符。如果您在不等待的情况下调用异步调用,您可能会在数据库中看到 3 个项目,因为数据库添加记录操作可以在检查后完成。我认为如果您使用同步方法,或者使用 async/await 进行修饰,您的单元测试会正常工作。

【讨论】:

    猜你喜欢
    • 2017-07-03
    • 2013-10-17
    • 2023-04-09
    • 2016-12-15
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    相关资源
    最近更新 更多