2016-03-07 64 views
0

我有以下的類結構:模擬設置例外爲有效設置

public class MyObj 
{ 
    public int Number; 
} 
public interface IService 
{ 
    int ProcessInt(MyObj obj); 
} 
public class Service : IService 
{ 
    public int ProcessInt(MyObj myObj) 
    { 
     return myObj.Number; 
    } 
} 

,然後消費類

public class Class1 
{ 
    public void Run(IService s) 
    { 
     var obj = new MyObj {Number = 1}; 
     Console.WriteLine(s.ProcessInt(obj)); 
    } 
} 

,然後將單元測試

[TestFixture] 
public class MyTest 
{ 

    private readonly Mock<IService> _service = new Mock<IService>(MockBehavior.Strict); 
    private readonly Class1 _sut = new Class1(); 

    [SetUp] 
    public void SetUp() 
    { 
     var obj = new MyObj {Number = 1}; 
     _service.Setup(x => x.ProcessInt(obj)).Returns(1); 
    } 

    [Test] 
    public void TestClass1() 
    { 
     _sut.Run(_service.Object); 
    } 
} 

問題我有,當我運行單元測試,我得到「Moq.MockException:IService.ProcessInt(MoqStu ff.MyObj)模擬行爲的調用失敗Strict.Mock上的所有調用都必須具有相應的設置。「這是奇怪的,因爲我有該輸入的設置。

這是起訂量框架的預期行爲嗎?有什麼辦法可以解決呢?

謝謝

回答

2

你有這樣的代碼在SetUp方法:

var obj = new MyObj {Number = 1}; 
_service.Setup(x => x.ProcessInt(obj)).Returns(1); 

在這裏,你設置的期望,即ProcessInt被稱爲與此特定對象obj

然而,在你的方法Run創建另一個對象:

var obj = new MyObj {Number = 1}; 

雖然屬性值是一樣的,這個對象是你在SetUp方法創建一個完全不同的。這就是爲什麼你會失去安裝程序的原因。

你可以做的,而不是設置您的服務使用It.IsAny任何輸入參數:

[SetUp] 
public void SetUp() 
{ 
    _service.Setup(x => x.ProcessInt(It.IsAny<MyObj>())).Returns(1); 
} 

此設置將爲任何參數值工作。

或者,如果你想只根據某些條件相匹配,您可以使用It.Is

[SetUp] 
public void SetUp() 
{ 
    // setup only for cases where obj.Number == 1 
    _service 
     .Setup(x => x.ProcessInt(It.Is<MyObj>(o => o.Number == 1))) 
     .Returns(1); 

    // setup only for cases where obj.Number == 2 
    _service 
     .Setup(x => x.ProcessInt(It.Is<MyObj>(o => o.Number == 2))) 
     .Returns(2); 
} 
+0

我不能這樣做,因爲我們說,我有10種元素和行爲的列表是一些其中我需要一個結果,而對於其他我需要另一個結果。所以我需要根據對象內部的值以某種方式進行模擬。 – kord

+0

@kord然後你可以使用'It.Is'。我更新了我的回答詳情 – dotnetom

+0

很酷。謝謝。有用! – kord