C# 使用Moq测试特定的实现

C# 使用Moq测试特定的实现,c#,unit-testing,moq,C#,Unit Testing,Moq,更新1,更多详细信息 我的问题很难解释,很抱歉 简单的问题。。。 如何使用Moq测试特定的实现 interface IShipping { int CalculateCost(); } class TruckShipping: IShipping { int CalculateCost() { return 9; } } class Shipping: IShipping { int CalculateCost() {

更新1,更多详细信息

我的问题很难解释,很抱歉

简单的问题。。。 如何使用Moq测试特定的实现

interface IShipping
{
    int CalculateCost();
}

class TruckShipping: IShipping
{
    int CalculateCost()
    {
        return 9;
    }
}

class Shipping: IShipping
{
    int CalculateCost()
    {
        return 5;
    }
}

class CalculateSomethingMore
{
    IShipping _shipping;
    CalculateSomethingMore(IShipping shipping)
    {
        // Here I want the TruckShipping implementation!
        _shipping = shipping;
    }
    DoCalc()
    {
        return _shipping.CalculateCost * 2;
    }
 }
如果没有mock,它可能看起来像(如果不使用DI) 测试:

NUnit、FluentAssertions、MbUnit、xUnit等。。没关系:)

测试: var truckShipping=模拟的?我想测试卡车运输的实现


然后将其注入CalculateMethingMore。

您可以使用mock来用伪造的轻量级对象替换真正的依赖项(通常过于复杂而无法实例化)。测试模拟对象毫无意义,因为本质上,您将测试来自某个第三方库的自动生成代码

编辑

现在还不清楚您为什么要依赖于具体的实现,特别是考虑到您正在使用IoC和inject
IShipping
。无论如何,我想你想要的是能够模拟卡车运输的东西,而不是卡车运输本身。如果是这样,很简单:

var shippingMock = new Mock<IShipping>();
// setting up mock to return 9 makes it behave as if it was TruckShipping
shippingMock.Stub(s => s.CalculateCost()).Returns(9);
var advancedCalculation = CalculateSomethingMore(shippingMock.Object);

var result = DoCalc();

var expected = 18;
Assert.IsTrue(result == expected);
var shippingMock=new Mock();
//将mock设置为return 9会使其行为类似于卡车运输
shippingMock.Stub(s=>s.CalculateCost()).Returns(9);
var advancedCalculation=CalculatesMethingMore(shippingMock.Object);
var result=DoCalc();
预期风险值=18;
Assert.IsTrue(结果==预期值);

Moq不是一个测试框架,它是一个mockinq框架,所以它不提供测试功能

对于您可以使用的测试,例如,您可以编写:

[TestMethod]
public void VerifyCostIsCorrect()
{
    new TruckShipping()
        .CalculateCost()
        .Should("The TruckShipping implementation returns a wrong cost.").Be.EqualTo(9);
}
如果要测试卡车运输实施,则需要对
TruckShipping
实施进行单独的测试

目前,您正在测试
CalculateMethingMore
的行为,该行为应返回成本的双倍值(按运费计算)。你不在乎哪一条船。
CalculateMethingMore
的职责是询问运输成本,并将成本翻一番:

Mock<IShipping> shipping = new Mock<IShipping>();
shipping.Setup(s => s.CalculateCost()).Returns(10);
CalculateSomethingMore sut = new CalculateSomethingMore(shipping.Object);
Assert.That(20, Is.EqualTo(sut.DoCalc()));
shipping.VerifyAll();

那不是我正在测试的模拟对象,为什么你忽略了模拟?请参阅我更新的问题:)您想测试卡车运输实现,那么,为什么要创建模拟?测试一个模拟对象没有意义,需要mockinq来设计问题,而不必担心实现。嗨,Matteo,我的问题没有更新。。。现在请看一下。对不起,我不明白你想做什么。你想测试卡车运输,那么,为什么要使用模拟?或者你只是想要一个使用Moq而不是卡车运输类的例子?我相信你看错了我的问题。。。我想测试的不是实际的模拟对象,而是使用模拟对象的类。请参阅我更新的问题:)@Janus007:您很少在测试中使用具体的实现,尤其是在模拟框架可用的情况下。mock为您提供了一些可以模拟这些具体实现的东西,而不是其他东西。查看我的编辑,让我知道这是否是您一直在寻找的。啊,我想我现在明白了,我想我应该专注于测试一个特定的实现,而事实上,模拟应该使用相关的值进行设置。感谢您的耐心。感谢您的澄清,这有助于我理解模拟和不同的实现(这并不重要)。我将此标记为接受,因为答案最全面。@Janus007欢迎:)顺便说一句,好的做法是测试中只有一个真实对象(您正在测试)。因此,如果某些依赖项的实现发生变化,您的测试不会失败。当您期望实际值为true时,也可以简单地使用
Assert.IsTrue(result)
Mock<IShipping> shipping = new Mock<IShipping>();
shipping.Setup(s => s.CalculateCost()).Returns(10);
CalculateSomethingMore sut = new CalculateSomethingMore(shipping.Object);
Assert.That(20, Is.EqualTo(sut.DoCalc()));
shipping.VerifyAll();
TruckShipping sut = new TruckShipping();
Assert.That(9, Is.EqualTo(sut.DoCalc());