2015-06-14 59 views
1

什麼時候我們需要使用Moq提供的.As方法?什麼時候應該使用Moq的.As方法?

從快速入門文檔:

// implementing multiple interfaces in mock 
var foo = new Mock<IFoo>(); 
var disposableFoo = foo.As<IDisposable>(); 
// now the IFoo mock also implements IDisposable :) 
disposableFoo.Setup(df => df.Dispose()); 

但我只是不明白爲什麼我們會想這樣做。你能給我一個實際的例子嗎?

回答

4

好了,這樣的例子。比方說,你有一個運輸管理軟件來管理汽車,航班等的移動。有不同的車輛,但他們在陸地或空中移動(沒有海,以簡化樣本)。

public interface IMovingOnLand 
{ 
    string Move(); 
} 

public interface IMovingInAir 
{ 
    string Move(); 
} 

並且有一個車輛/飛機的快速運輸選項。

public interface IExpressTransport 
{ 
    string MoveDirectly(); 
} 

有一個運輸經理班負責移動所有的車輛/飛機。它處理運輸位的表達方式不同於普通的人(爲了簡化該樣本中起見,只打印取決於它是否是IExpressTransport與否不同的消息):

public class TransportManager 
{ 
    public string MoveItem(IMovingInAir airCraft) 
    { 
     if (airCraft is IExpressTransport) 
     { 
      return "Message from an express aircraft: " + 
       ((IExpressTransport)airCraft).MoveDirectly(); 
     } 
     return "Message from an aircraft: " + airCraft.Move(); 
    } 

    public string MoveItem(IMovingOnLand landVehicle) 
    { 
     if (landVehicle is IExpressTransport) 
     { 
      return "Message from an express land vehicle: " + 
       landVehicle.Move() + 
       ((IExpressTransport)landVehicle).MoveDirectly(); 
     } 
     return "Message from a land vehicle: " + landVehicle.Move(); 
    } 
} 

現在你想測試一個飛機的表現與汽車不同。而且,如果定期航班的處理與明確的航班不同。所以你測試你的對象爲IMovingInAir對象和IExpressTransport。要僅測試飛行行爲,您可以簡單地將其創建爲Mock<IMovingInAir>。但要延長航班的明確一個,你必須使用As<IExpressTransport>()方法:

[TestMethod] 
public void TestTransportManager() 
{ 
    TransportManager manager = new TransportManager(); 

    // Create a regular flight. 
    var flight = new Mock<IMovingInAir>(); 
    flight.Setup(x => x.Move()) 
     .Returns("Air craft moved to next stop."); 

    // Create a flight. 
    var flightExpress = new Mock<IMovingInAir>(); 
    // Add standard behaviour. 
    flightExpress 
     .Setup(x => x.Move()) 
     .Returns("Air craft moved to next stop."); 
    // Extend to express and add express flight behaviour. 
    flightExpress 
     .As<IExpressTransport>() 
     .Setup(x => x.MoveDirectly()) 
     .Returns("Air craft moved directly to destination."); 

    // Get the results. 
    var res = manager.MoveItem(flight.Object); 
    var resExp = manager.MoveItem(flightExpress.Object); 

    // Sssert flight and express fligh returned different messages. 
    Assert.AreNotEqual(res, resExp); 

    // Assert the expected messages have been returned. 
    Assert.AreEqual("Message from an aircraft: Air craft moved to next stop.", res); 
    Assert.AreEqual("Message from an express aircraft: Air craft moved directly to destination.", resExp); 
} 
+0

謝謝!這讓我很清楚。 – user11081980

4

當你需要測試實現多個接口的對象可以使用作爲方法。
this示例中,如果輸入對象也實現了IDisposable,則測試代碼具有特定的行爲。事情是這樣的:

public void Execute(IFoo input) 
{ 
    // do process... 

    IDisposable disposable = input as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

類的實現:

public class ConcreteFoo: IFoo, IDisposable 
{ 
    ... 
} 

編輯

起訂量的配置需要:

var foo = new Mock<IFoo>(); 
var disposableFoo = foo.As<IDisposable>(); 
disposableFoo.Setup(df => df.Dispose()); 

// Verify whether the Dispose() method was called 
// That's true only if we use the As method from Moq. 
testedClass.Execute(disposableFoo); 
disposableFoo.Verify(m => m.Dispose()); 
+1

這不是起訂量的作爲,那是C#的關鍵字 – CRice

+1

@CRice,測試「爲」 C#的關鍵字,你需要使用de Moq的「As」通用方法。 –

+1

感謝您的編輯更有意義 – CRice

相關問題