我正在开发一个使用Entity Framework,Repository-Pattern,UnitOfWork-Pattern和Moq的C#项目。 我是EF和使用Moq的单元测试的新手并且遇到了以下问题: 当我尝试从服务类测试方法时,我得到空指针......似乎上下文无法实例化。任何人都可以指出我的错误或给我一个链接吗?
示例:
portionService.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();
}
portionServiceTests.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();
}
答案 0 :(得分:2)
基于EF的应用程序单元测试实际上并不容易。我建议使用像effort这样的库来模拟实体框架。
答案 1 :(得分:2)
您正在尝试将模拟结果验证到数据库中的实际数据,这就是它失败的原因。您的单元测试应该测试服务,并且服务调用上下文,而不是服务本身的模拟。
以下示例使用Rowan Miller's article中的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");
}
}
}