C# Moq框架:模拟添加对象

C# Moq框架:模拟添加对象,c#,entity-framework,unit-testing,moq,nullreferenceexception,C#,Entity Framework,Unit Testing,Moq,Nullreferenceexception,我刚开始使用Moq进行单元测试,但在尝试向repo添加对象时遇到了问题。基本上,我们有一个代表数据库结构的接口。此接口包含表示该数据库中数据的其他接口,如下所示: public interface IUnitOfWork : IDisposable { IRepository<Order> OrdersRepo { get; } IRepository<Customer> CustomerRepo { get; } IRepository<P

我刚开始使用Moq进行单元测试,但在尝试向repo添加对象时遇到了问题。基本上,我们有一个代表数据库结构的接口。此接口包含表示该数据库中数据的其他接口,如下所示:

public interface IUnitOfWork : IDisposable
{
    IRepository<Order> OrdersRepo { get; }
    IRepository<Customer> CustomerRepo { get; }
    IRepository<Product> ProductsRepo { get; }
}
公共接口IUnitOfWork:IDisposable
{
i存储顺序repo{get;}
IRepository CustomerReporto{get;}
IRepository ProductsRepo{get;}
}
创建模拟IUnitOfWork没有问题,当我尝试将order对象添加到OrdersRepo时会出现问题,如下所示:

[TestClass]
public class OrderTest
{
    private Mock<IUnitOfWork> mockDB = new Mock<IUnitOfWork>();
    private IUnitOfWork testDB;
    private Order testOrder;

    [TestInitialize]
    public void Initialize()
    {
        //Create the test order
        testOrder = new Order();
        testOrder.ID = 123;

        //Setting up the Moq DB
        testDB = mockDB.Object;
    }

    [TestMethod]
    public void AddOrder_ValidOrder_OrderAdded()
    {   
        testDB.OrdersRepo.Add(testOrder);
    }
}
[TestClass]
公共类顺序测试
{
私有Mock mockDB=new Mock();
私有IUnitOfWork测试数据库;
私人订单测试订单;
[测试初始化]
公共无效初始化()
{
//创建测试顺序
testOrder=新订单();
testOrder.ID=123;
//建立最小起订量数据库
testDB=mockDB.Object;
}
[测试方法]
public void AddOrder_ValidOrder_OrderAdded()
{   
testDB.ordersepo.Add(testOrder);
}
}
当我尝试添加订单时,我不断得到一个NullReferenceException。我认为这是因为testDB中的ordersepo是一个接口。然而,当我尝试为此创建一个模拟repo时,我得到一个错误,即ordersepo是只读的,因为它是{get;}而不是{get;set;}


我是否可以使用Moq测试在回购仅为get时添加我的订单对象;这是一个接口吗

您将获得NullReferenceException,因为您尚未设置模拟对象。如果只想设置1个属性,请使用

mockDB.SetupProperty(self => self.OrdersRepo);
如果要将属性设置为使用自己的可枚举项,可以使用

var collection = <Init collection here>;
mockDB.SetupGet(self => self.OrdersRepo).Returns(collection);
mockDB.SetupAllProperties();

您将获得NullReferenceException,因为您尚未设置模拟对象。如果只想设置1个属性,请使用

mockDB.SetupProperty(self => self.OrdersRepo);
如果要将属性设置为使用自己的可枚举项,可以使用

var collection = <Init collection here>;
mockDB.SetupGet(self => self.OrdersRepo).Returns(collection);
mockDB.SetupAllProperties();

如果你想测试你的订单回购协议,那么你不需要通过IUnitOfWork然后模仿订单回购协议,因为这样你就不需要测试你的主体。您应该实例化订单回购的具体内容,并调用应该可以公开访问的Add方法。也许您需要模拟您的orders repo调用的底层DB客户机来调用DB,但这是另一回事


希望这能有所帮助。

如果你想测试你的订单回购协议,那么你不需要通过IUnitOfWork然后模仿订单回购协议,因为这样你就不需要测试你的主题。您应该实例化订单回购的具体内容,并调用应该可以公开访问的Add方法。也许您需要模拟您的orders repo调用的底层DB客户机来调用DB,但这是另一回事


希望这能有所帮助。

看起来你在一次测试中做的太多了。您正在测试什么功能?您的DB或OrdersRepo?不是回答您问题的主题,但更好的编码实践建议是不要从您的UnitOfWork中公开这些存储库中的每一个。提取出它们要保存到的对象,并且在您的UnitOfWork上只有一个方法来保存每个对象(或每个对象的基础,并在方法内部确定如何保存它),然而,现实世界的方法需要数据库,所以这就是为什么我对UnitOfWork进行了模拟,看起来您试图在一个测试中做太多的事情。您正在测试什么功能?您的DB或OrdersRepo?不是回答您问题的主题,但更好的编码实践建议是不要从您的UnitOfWork中公开这些存储库中的每一个。抽象出它们被保存到的对象,并且在你的UnitOfWork上只有一个方法来保存每个对象(或者每个对象的一个基础,并在方法内部确定如何保存)。只是我的orders repo,但是真实世界的方法会接收数据库,所以这就是为什么我有UnitOfWork的模拟