我是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并验证子属性。
答案 0 :(得分:2)
模拟不记得属性的值,除非你告诉它:
i.Model = new DummyModel();
将导致模拟记住您将其设置为该对象。但是,如果您访问该属性,它仍将返回null。如果您希望它的行为类似于自动属性,请使用:
mock.SetupAllProperties();
现在
i.Model.MyProperty = "foo";
不会再失败了。使用模拟,您始终需要明确指定所有行为。
答案 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()更多的东西,而不是默认的模拟。