2012-06-07 68 views
2

有了Moq,是否有可能設置一個模擬屬性,使它發生變異?嘲諷的副作用

例如,給定:

public interface IService // To be mocked. 
{ 
    bool IsConnected { get; } 
} 

是否有可能設置IService的模擬,使得以下通行證?

var mockService = new Mock<IService>(); 

// Setup mockService so IsConnected mutates...? 

bool before = mockService.Object.IsConnected; 

bool after = mockService.Object.IsConnected; 

Assert.AreNotEqual(before, after); 

當然這個設置並不做的伎倆:

mockService.SetupGet(service => service.IsConnected).Returns(false); 
mockService.SetupGet(service => service.IsConnected).Returns(true); 

是一致的我的理解,起訂量不執行記錄/回放模式。

這裏是一個小更現實的例子:

public interface IService // To be mocked. 
{ 
    bool IsConnected { get; } 

    void Connect(); // Mutates IsConnected. 
} 

class Client // To be tested 
{ 
    private readonly IService service; 

    public Client(IService service) 
    { 
     this.service = service; 
    } 

    public bool DoWork() 
    { 
     if (!service.IsConnected) // In test, IsConnected should return false. 
     { 
      service.Connect(); 
     } 

     if (!service.IsConnected) // In test, IsConnected should return true. 
     { 
      return false; 
     } 

     // ... yada yada yada more code 

     return true; 
    } 
} 

我使用起訂量4.0.10827.0。

+0

你確定你正在測試正確的東西嗎?根據我的經驗,當你嘗試做這樣的事情時,你通常在你的單位範圍之外進行測試。 =>在這種情況下:是否爲ClientTest導入測試服務?這不應該發生在ServiceTest中嗎? –

+0

@ Team-JoKi好點。理想情況下,連接狀態將成爲DoWork測試的前提條件。理想的情況下。 – Watsontap

回答

3

您可以設置返回到Func<bool>而不是布爾值。然後你會寫這個func,以便改變它的結果。喜歡的東西....

bool isConnected = false 
var mockService = new Mock<IService>(); 
// Setup mockService so IsConnected mutates...? 
mockService.Setup(s => s.Connect()).Callback(() => isConnected = true); 
mockService.SetupGet(s => s.IsConnected).Returns(() => isConnected); 

bool before = mockService.Object.IsConnected; 

mockService.Object.Connect(); 

bool after = mockService.Object.IsConnected; 

Assert.AreNotEqual(before, after); 

然而,根據您的serivce如何變得複雜,你可能要考慮制定FakeService和使用而不是嘲笑。

+0

我實際上是從一個FakeService開始的,但後來決定用模擬來嘗試,這導致我在這裏。謝謝。 – Watsontap