2016-08-15 77 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中提出的測試用例僅對測試具體類與其他類的交互有效。