嘲弄ChildProperty无法让它工作?

时间:2010-02-05 18:40:29

标签: moq

我正在尝试测试嵌套在子类中的属性。 我总是得到一个错误。 我错过了什么吗? 是否可以在moq中测试子属性。

我有以下

     [Test]
public void Should_be_able_to_test_orderCollection()
    {
        var orderViewMock = new Mock<IOrderView>();
        orderViewMock.SetupGet(o => o.Customer.OrderDataCollection.Count).Returns(2);          

        orderViewMock.SetupSet(o => o.Customer.OrderDataCollection[1].OrderId = 1);

        orderViewMock.VerifySet(o => o.Customer.OrderDataCollection[1].OrderId=1);
    }

    public class CustomerTestHelper
    {
        public static CustomerInfo GetCustomer()
        {
            return new CustomerInfo
           {
               OrderDataCollection = new OrderCollection
                 {
                     new Order {OrderId = 1},
                     new Order {OrderId = 2}
                 }
           };

        }
    }
    public class CustomerInfo
    {
        public OrderCollection OrderDataCollection { get; set; }
    }

    public class OrderCollection:List<Order>
    {
    }

    public class Order
    {
        public int OrderId { get; set; }
    }
    public interface  IOrderView
    {
        CustomerInfo Customer { get; set; }
    }

3 个答案:

答案 0 :(得分:3)

您无法模拟CustomerInfo的OrderDataCollection属性,因为它是具体类的非虚拟属性。

解决这个问题的最佳方法是从CustomerInfo中提取一个接口,然后让IOrderView返回:

public interface IOrderView
{
    ICustomerInfo Customer { get; set; }
}

答案 1 :(得分:1)

如果你有正确的抽象,这绝对是可能的。你需要嘲笑你的Customer及其子女,为你的榜样工作,例如:

var customerMock = new Mock<ICustomer>();
orderViewMock.SetupGet(o => o.Customer).Returns(customerMock.Object);

等。对于要使用模拟控制的子对象的整个层次结构。希望它有意义。

/克劳斯

答案 2 :(得分:0)

您将收到运行时错误,如您所见:

System.ArgumentException: Invalid setup on a non-overridable member:
o => o.Customer.OrderDataCollection.Count
at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo methodInfo)

您可以模拟IOrderView并返回所需的任何CustomerInfo实例,但您也尝试模拟CustomerInfo和OrderCollection。正如Mark Seemann所提到的,您只能模拟接口和虚拟属性/方法。除了Typemock(商业)之外,这几乎适用于任何模拟/隔离框架。

正如其他人已经说过的,解决问题的一种方法是为客户返回一个界面。