1

我正在开发一个使用实体框架、存储库模式、UnitOfWork 模式和起订量的 C# 项目。我是 EF 和 Moq 单元测试的新手,遇到了以下问题:当我尝试测试服务类中的方法时,我得到了空指针……而且似乎无法实例化上下文。谁能指出我的错误或提供链接?

例子:

部分服务.cs

/// <summary>
/// The PortionService class represents a service for the Portion model.
/// </summary>
public class PortionService : Service, IPortionService
{
    /// <summary>
    /// In this constructor the base constructor of the Service class is called.
    /// </summary>
    /// <param name="context">Represents a context of the data access layer.</param>
    public PortionService(IDALContext context) : base(context) { }

    public void Add(Portion portion)
    {
        context.Portion.Create(portion);
        context.SaveChanges();
    }

    public Portion GetPortionByName(string name)
    {
        return context.Portion.GetAll().Where(p => p.Name.ToUpper() == name.ToUpper()).LastOrDefault();
    }

部分ServiceTests.cs

// TestClass for PortionService-Tests
[TestClass]
public class PortionServiceTests
{
    private PortionService _portionService;

    // define the mock object
    private Mock<IPortionService> _portionServiceMock;

    [TestInitialize]
    public void Init()
    {
        _portionService = new PortionService(new DALContext());

        // create the mock object
        _portionServiceMock = new Mock<IPortionService>();
    }[TestMethod]
    public void EnteringPortionNameReturnsThePortion()
    { 
    //arrange
    // arrange data
    Portion portion = new Portion { PortionID = 12, Name = "testPortion" };

    //arrange expectations 
    _portionServiceMock.Setup(service => service.GetPortionByName("testPortion")).Returns(portion).Verifiable();

    //act
    var result = _portionService.GetPortionByName("testPortion");

    //verify
    Assert.AreEqual(portion, result.Name);
    }

DALContext.cs

    public class DALContext : IDALContext, IDisposable
{
    /// <summary>
    /// The _context property represents the context to the current Database.
    /// </summary>
    private DatabaseContext _context;

    private Repository<Portion> _portionRepository;
...
    /// <summary>
    /// In this constructor the single instance of the DataBaseContext gets instantiated.
    /// </summary>
    public DALContext()
    {
        _context = new DatabaseContext();
    }
4

2 回答 2

2

对基于 EF 的应用程序进行单元测试实际上并不容易。我建议使用类库模拟实体框架。

于 2013-05-23T13:24:43.700 回答
2

您正在尝试将模拟结果验证为数据库中的实际数据,这就是它失败的原因。您的单元测试应该测试服务,并且服务调用上下文,而不是服务本身的模拟。

以下示例使用Rowan Miller 文章中的FakeDbSet 方法。

using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
using SharpTestsEx;

namespace StackOverflowExample.EntityFramework
{
    public class DataEntity
    {
        public int Id { get; set; }
        public string Data { get; set; }
    }

    public interface IContext
    {
        IDbSet<DataEntity> DataEntities { get; }
    }

    public class DataService
    {
        private IContext _db;
        public DataService(IContext context)
        {
            _db = context;
        }

        public DataEntity GetDataById(int id)
        {
            return _db.DataEntities.First(d => d.Id == id);
        }
    }

    [TestFixture]
    public class DataServiceTests
    {
        [Test]
        public void GetDataByIdTest()
        {
            //arrange
            var datas = new FakeDbSet<DataEntity>
                {
                    new DataEntity {Id = 1, Data = "one"},
                    new DataEntity {Id = 2, Data = "two"}
                };
            var context = new Mock<IContext>();
            context.SetupGet(c => c.DataEntities).Returns(datas);
            var service = new DataService(context.Object);

            //act
            var result = service.GetDataById(2);

            //assert
            result.Satisfy(r =>
                           r.Id == 2
                           && r.Data == "two");
        }
    }
} 
于 2013-05-23T13:43:04.830 回答