单元测试使用Moq和Nunit抛出“System.NullReferenceException”

时间:2010-06-30 17:39:04

标签: c# nunit moq

我是moq和单元测试的新手。所以,我不太了解它。请原谅我,如果问题是愚蠢的。请帮我理解以下场景。

以下是我的简单测试

[Test]
public void TryMoq() {
    var mock = new Mock<IDummyInterface>();
    var dummy = new DummyClass(mock.Object);
    mock.VerifySet(m => m.Model = It.Is<DummyModel>(mo => mo.MyProperty == "foo"));
}

和我试图测试的代码

public class DummyClass
{
    public DummyClass(IDummyInterface i) {
        i.Model = new DummyModel() ;
        i.Model.MyProperty = "foo";

    }
}

public class DummyModel
{
    public string MyProperty { get; set; }
}

public interface IDummyInterface {
     DummyModel Model { get; set; }
}

现在排在“i.Model.MyProperty =”foo“;”正在抛出“System.NullReferenceException”。

为什么,我认为自从我使用Moq以来的原因。

奇怪的是,如果我改变了“DummyClass”的构造函数。喜欢这个

public DummyClass(IDummyInterface i)
    {
        i.Model = new DummyModel() { MyProperty ="foo"};
        //i.Model.MyProperty = "foo";

    }

测试通行证。在第二种情况下,即使我尝试将“foo”的值更改为“bar”。测试失败。(虽然这很好)。

我只想了解最新情况。我怎么想moq并验证子属性。

3 个答案:

答案 0 :(得分:2)

模拟不记得属性的值,除非你告诉它:

i.Model = new DummyModel();

将导致模拟记住您将其设置为该对象。但是,如果您访问该属性,它仍将返回null。如果您希望它的行为类似于自动属性,请使用:

mock.SetupAllProperties();

现在

i.Model.MyProperty = "foo";

不会再失败了。使用模拟,您始终需要明确指定所有行为。

详细了解:http://code.google.com/p/moq/wiki/QuickStart

答案 1 :(得分:1)

这两种情况的区别在于你写的时候

i.Model = new DummyModel() { MyProperty ="foo"};

你基本上是在写

var dummyModel = new DummyModel() { MyProperty ="foo"};
i.Model = dummyModel;

也就是说,您将属性已设置为“Foo”的对象传递给您的接口。你的测试断言“有人会尝试将Mock上的属性设置为DummyModel类型的对象,其中属性MyProperty设置为”Foo“”,这正是发生的事情。

第一种情况失败,因为在执行以下行之后,i.Model为空。

i.Model = new DummyModel();

直接在Mock上获取或设置属性不会设置属性,它将不执行任何操作或返回null,除非您指定要执行的操作。因此,在这种情况下,在构造函数的第二行中,i.Model为null,这会导致i.Model.MyProperty上的null异常。

答案 2 :(得分:1)

您还可以执行以下操作:

var mock = new Mock<IDummyInterface>();
mock.SetupSet(m => m.Model = It.Is<DummyModel>(mo => mo.MyProperty == "foo")).Verifiable();

var dummy = new DummyClass(mock.Object);

mock.Verify();

Moq m.Model的默认实现是返回null,所以你需要给Dummy()更多的东西,而不是默认的模拟。