2016-08-15 81 views
2

我想单元测试使用Moq。下面是示例代码:如何使用Moq设置只读属性?

public class ConcreteClass 
{ 
    private readonly FirstPropery firstProperty; 
    private readonly SecondProperty secondProperty; 

    public ConcreteClass(firstProperty, secondProperty) 
    { 
     this.firstProperty = firstProperty; 
     this.secondProperty = secondProperty; 
    } 
} 

[TestMethod] 
    var concreteClassMock = new Mock<ConcreteClass>() { CallBase = true }; 

在我的测试方法,我想设置firstProperty引用一个真正的对象FirstProperty对象(由工厂创建的),后来又用它来测试另一个对象的行为。有什么办法可以实现吗?

+2

您不要模拟私人内容。模拟应该独立于某些实现。 – poke

回答

2

通常情况下,你不会嘲笑私有成员,因为你只是嘲讽的东西公共接口。因此,模拟完全独立于实现细节。

话虽这么说,你可以通过构造函数参数的Mock构造函数将被传递给目标的构造函数:

new Mock<ConcreteClass>(firstProperty, secondProperty) {CallBase = true}; 

然而,如果你的目标是实际测试ConcreteClass,你应该不是创建它的模拟。你应该测试实际的对象。所以嘲笑它的依赖关系,并在必要时通过这些依赖关系,但保持你想测试的对象实际上是真实的。否则,您可能会引入和测试来自模拟的行为而不是您正在测试的对象:

var firstMock = new Mock<FirstProperty>(); 
var secondMock = new Mock<FirstProperty>(); 

var obj = new ConcreteClass(firstMock.Object, secondMock.Object); 

obj.DoSomething(); 
// assert stuff 
+0

模拟混凝土类,通过构造函数传递参数和简单的“新的ConcreteClass(param1,param2)”有什么区别?我在谈论场景,当你真的需要模拟一个对象来设置它在构造函数中的只读属性。把这个嘲弄的对象传递给将要测试的对象为什么不只是“新增” –

+0

@LouisaBickley我不完全确定你的意思,但它取决于你想测试什么,如果你想测试类'X'的构造函数,那么你不应该嘲笑它,因为嘲笑用你的模拟行为“替换”了实际的实现。如果你想测试一个依赖于'X'的不同类'Y',那么你应该模拟'X',以便'X'的实现细节不会影响'Y'的测试 - 也许你可以开一个新的问题,所以我们可以进一步讨论这个细节。 – poke

1

一个几句话:

1 - 它可以用这样一个接口和一个get方法来轻松实现:

public interface IConcreteClass 
{ 
    FirstProperty FirstProperty { get; } 
} 

    [Test] 
    public void TestCase() 
    { 
     var yourFirstPropertyImplementation = new FirstProperty(); 
     var concreteClassMock = new Mock<IConcreteClass>(); 
     concreteClassMock.Setup(o => o.FirstProperty).Returns(yourFirstPropertyImplementation); 
    } 

2 - 根据您的方案,你真的需要一个起订量,为什么不仅仅使用真正的实现并仅在边界使用moq?

3-你应该说明你想测试什么?如果它是具体的课程?或属性?或其他一些类?我在1中提出的测试用例仅对测试具体类与其他类的交互有效。