Mock.Of <object> VS Mock <object>()

时间:2016-05-05 04:53:55

标签: c# unit-testing testing mocking moq

我目前对如何模仿感到困惑。

我正在使用Moq。要模拟对象,我通常会这样写

 var mockIRepo = new Mock<IRepo>();

但是,我需要为我的设置创建模拟对象。

选项1 以这种方式模拟仅包含属性的对象是否更好?

 var object = Mock.Of<Object>()

选项2 或者这样

 var object = new Mock<Object>()

我读过选项2有setupproperties这对我有点疑问,因为我也可以在选项1中设置属性。

那有什么区别?或者有更好的方法吗?

4 个答案:

答案 0 :(得分:23)

这篇文章帮助我理解Mock.Of&lt; T&gt; : Old style imperative Mock<T> vs functional Mock.Of<T>

如帖子中所解释的,使用Mock.Of&lt; T&gt;你说的是“给我一个行为像这样的模拟”(或模拟 s 。如果你需要获得许多对象(IEnumerable),那么&lt; T&gt;)。它使模拟的声明更简洁。

Mock&lt; T&gt;的示例(返回模拟)

var el1 = new Mock<IElementInfo>();
el1.Setup(x => x.Id).Returns(Guid.NewGuid());
el1.Setup(x => x.Multiplicity).Returns(Multiplicity.Single);

var c1 = new Mock<ICollectionInfo>();
c1.Setup(x => x.Id).Returns(Guid.NewGuid());
c1.Setup(x => x.Multiplicity).Returns(Multiplicity.Multiple);

var p1 = new Mock<IPropertyInfo>();
p1.Setup(x => x.Id).Returns(Guid.NewGuid());
p1.Setup(x => x.Name).Returns("Foo" + Guid.NewGuid().ToString());
p1.Setup(x => x.Type).Returns("System.String");

var p2 = new Mock<IPropertyInfo>();
p2.Setup(x => x.Id).Returns(Guid.NewGuid());
p2.Setup(x => x.Name).Returns("Bar" + Guid.NewGuid().ToString());
p2.Setup(x => x.Type).Returns("System.String");

var elementInfoMock = new Mock<IElementInfo>();
elementInfoMock.Setup(e => e.Id).Returns(Guid.NewGuid());
elementInfoMock.Setup(e => e.Multiplicity).Returns(Multiplicity.Multiple);
elementInfoMock.Setup(e => e.Elements)
    .Returns(new List<IAbstractElementInfo>
    {
        el1.Object,
        c1.Object,
    });
elementInfoMock.Setup(x => x.Properties).Returns(
    new List<IPropertyInfo>
    {
        p1.Object,
        p2.Object,
    });

this.elementInfo = elementInfoMock.Object;

使用Mock.Of&lt; T&gt;的相同示例(返回类的实例)

this.elementInfo = Mock.Of<IElementInfo>(x =>
x.Id == Guid.NewGuid() &&
x.Multiplicity == Multiplicity.Multiple &&
x.Elements == new List<IAbstractElementInfo>
{
    Mock.Of<IElementInfo>(e => e.Id == Guid.NewGuid() && e.Multiplicity == Multiplicity.Single),
    Mock.Of<ICollectionInfo>(e => e.Id == Guid.NewGuid() && e.Multiplicity == Multiplicity.Single),
} &&
x.Properties == new List<IPropertyInfo>
{
    Mock.Of<IPropertyInfo>(p => p.Id == Guid.NewGuid() && p.Name == "Foo" + Guid.NewGuid() && p.Type == "System.String"),
    Mock.Of<IPropertyInfo>(p => p.Id == Guid.NewGuid() && p.Name == "Foo" + Guid.NewGuid() && p.Type == "System.String"),
});

答案 1 :(得分:3)

基于上述答案,我猜想当您最想模拟属性时,Mock.Of<T>()更容易,而当您想模拟方法等时,Mock<T>更容易。

  • 大多数模拟属性:
var foo = Mock.Of<Foo>();
foo.Property1 = 1;
foo.Property2 = 2;
foo.Property3 = 3;
  • 大多数模拟方法:
var barMock = new Mock<Bar>();
barMock.Setup(bar => bar.GetValue1()).Returns(1);
barMock.Setup(bar => bar.GetValue2Async()).ReturnsAsync(2);

答案 2 :(得分:2)

两者都是一样的,但使用Mock.Of则更“自然”。

使用Mock<T>看起来更像是这样(或使用代码进行设置/返回):

var mockService = new Mock<ISomeService>();
mockService.SetupProperty(s => s.IsActive);
mockService.Object.IsActive = true;
mockService.SetupProperty(s =>s.DelayTime);
mockService.Object.DelayTime = 5000;

使用Mock.Of<T>可以直接获取实例,并且可以设置所需的值。 您可以使用Mock.Get()来配置任何方法:

var mockService = Mock.Of<ISomeService>();
mockService.IsActive = true;
mockService.DelayTime = 5000;
Mock.Get(mockService).Setup(s => s.ExecuteTask()).Returns(true);

它们的作用相同,但是对于具有许多属性和方法的更复杂的服务,我认为Mock.Of<T>更具可读性

答案 3 :(得分:-5)

这就是为什么我不喜欢所有变量的var关键字。选项2返回Mock&lt; T&gt;。而选项1返回T.基本上它只是语法差异。您可以以不同的方式模拟方法。见文档。