何时应使用 .作为最小起订量的方法

本文关键字:方法 何时应 | 更新日期: 2023-09-27 17:56:25

我们什么时候需要使用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());

但我就是不明白我们为什么要这样做。你能给我举一个实际的例子吗?

何时应使用 .作为最小起订量的方法

当需要测试实现多个接口的对象时,可以使用 As 方法。
在此示例中,如果输入对象也实现 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());

好的,举个例子。假设您有一个运输管理软件来管理汽车、航班等的移动。有不同的车辆,但它们在陆地或空中移动(没有海洋来简化样本)。

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);
}