适合使用类为单元测试创建虚拟数据

本文关键字:单元测试 创建 虚拟 数据 | 更新日期: 2023-09-27 18:35:04

我正在尝试做一些单元测试,我需要虚拟数据。其中一些数据我需要有特定的值,其他的只是随机的。

例如,我的服务层中有一个"CreateProduct"方法,我想知道在我的单元测试中使用这样的方法而不是手工制作产品是否是一个好主意。

从表面上看,这似乎是一个好主意,但我担心也许我需要嘲笑或其他东西才能成功通过这种方法。

CreateProduct 将尝试将产品保存到数据库,但我已经有一个标志可以停止保存发生(用于回滚的工作单元场景(。

我正在使用EF 6-rc1并使用最小起订量模拟DataContext,我打算使用AutoFixture,但它对于这个secnario来说不是开箱即用的,我开始觉得我一次使用了太多的新工具,所以也许我现在应该手动完成。

适合使用类为单元测试创建虚拟数据

如果没有代码示例,很难确切地说出您在做什么,但我有时会使用这种使用内存中ListIDataSet实现。典型的用法是这样的:

using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
namespace EFMock
{
    internal interface IDataContext
    {
        IDbSet<DataItem> DataItems { get; set; }
    }
    class DataContext : DbContext, IDataContext
    {
        public IDbSet<DataItem> DataItems{ get; set; }
    }
    class DataItem
    {
        public int SomeNumber { get; set; }
        public string SomeString { get; set; }
    }
    /* ----------- */
    class DataUsage
    {
        public int DoSomething(IDataContext dataContext)
        {
            return dataContext.DataItems.Sum(x => x.SomeNumber);
        }
    }
    /* ----------- */
    [TestFixture]
    class TestClass
    {
        [Test]
        public void SomeTest()
        {
            var fakeDataItems = new [] {
                new DataItem { SomeNumber = 1, SomeString = "One" },
                new DataItem { SomeNumber = 2, SomeString = "Two" }};
            var mockDataContext = new Mock<IDataContext>();
            mockDataContext.SetupGet(x => x.DataItems).Returns(new FakeDbSet<DataItem>(fakeDataItems));
            var dataUsage = new DataUsage();
            var result = dataUsage.DoSomething(mockDataContext.Object);
            Assert.AreEqual(2, result);
        }
    }
}

我还有一个名为"FakeO"的NuGet包,可用于创建一些假对象,其中有些数据是特定值,有些是随机的:

var fakeDataItems = FakeO.Create.Fake<DataItem>(10, // create an IEnumerable of 10 items
    x => x.SomeNumber = FakeO.Number.Next(),        // set to a random number
    x => x.SomeString = "Always This String");      // set to a specific string

在进行此类测试时要记住的一件事是,对List使用IQueryable将使用 Linq2Objects 而不是 Linq2Entities,因此某些 Linq 查询的结果会有所不同。

如果你想对某些东西进行单元测试,你只需要测试这个单元。如果使用服务层中的某个方法生成一些假数据,则单元测试不仅是测试被测单元,还要测试服务层中的方法。

所以你的问题的答案是:不,使用服务层来虚拟数据不是一个好主意