【问题标题】:stub out a method like an interface using nsubstitute使用 nsubstitute 存根类似接口的方法
【发布时间】:2014-11-10 23:27:13
【问题描述】:

这是我的第一篇文章!

我正在尝试使用 nsubstitute 编写单元测试,但我发现最后一点很困难。

我在下面包含了一段 sn-p 代码,在模型上调用该方法时测试失败。是否可以将这种方法存根?类似于如果它是一个接口

干杯,伙计们!期待您的回复

詹姆斯

我的单元测试尝试

public class MyTests
{
    private IModelMapper _modelMapper;

    [SetUp]
    public void Setup()
    {
        _modelMapper = Substitute.For<IModelMapper>();
    }

    [Test]
    public void GetModel_Returns_A_Model()
    {
        var result = theClass.GetModel(new Booking {CurrencyCode = ""}, null);

        **UPDATE to include assert**

        // Assert
        Assert.IsInstance<BasketModel>(result);
    }
}

功能代码

public Model GetModel(Booking booking)
{
    var model = _modelMapper.Map(booking);

    // Is it possible to stub this out?  Similar to if it was an interface
    model.FormatPricing(somethingHere);

    return model;
}

更新 - 说明返回类型

BasketModel model = _modelMapper.Map(booking);

更新 #2 - 包括返回

var basketModel = new BasketModel();
BasketModel model = _modelMapper.Map(booking).Returns(basketModel);

【问题讨论】:

  • _modelMapper.Map(booking)的返回类型是什么?如果它是一个接口,那么你可以存根它。
  • 它不是一个接口,它是一个类。
  • 好的,最简单的方法是实现一个假模型并让你的存根 IModelMapper 返回它。我会发布一个答案,但我个人对 nSubstitute 并不熟悉。此外,了解您要测试的内容会很有帮助。您的测试方法不包含断言。
  • 我添加了断言,只是为了检查方法的返回类型
  • 能否提供一个示例链接?

标签: c# unit-testing nsubstitute


【解决方案1】:

您能否提供您收到的测试失败消息?

以下是我倾向于对此类代码采取的一般方法。假设我们将IModelMapper 注入到被测类中(近似代码;我还没有测试过):

[SetUp]
public void Setup()
{
    _modelMapper = Substitute.For<IModelMapper>();
    theClass = new TheClass(_modelMapper);
}
[Test]
public void GetModel_Returns_Model_From_Mapper()
{
    // Arrange
    var booking = new Booking { CurrencyCode = "" };
    var expectedModel = new BasketModel();
    _modelMapper.GetModel(booking).Returns(expectedModel);

    // Act
    var result = theClass.GetModel(booking, null);

    // Assert
    Assert.AreSame(expectedModel, result);
}

如果你想删除BasketModel.FormatModel(这是一个很大的“如果”。如果可能的话,我建议使用真实类型),那么你也需要替换BasketModel

小心 - NSubstitute 不适用于非虚拟方法,因此您可能需要BasketModel 的接口,或者确保在任何地方都使用虚拟方法。 (同样,前面有未经测试的代码)

[Test]
public void ModelReturnedShouldBeFormatted()
{
    // Arrange
    var booking = new Booking { CurrencyCode = "" };
    var expectedModel = Substitute.For<IBasketModel>();
    _modelMapper.GetModel(booking).Returns(expectedModel);

    // Act
    var result = theClass.GetModel(booking, null);

    // Assert
    expectedModel.Received().FormatModel(Arg.Any<SomethingHere>());
}

这是测试对特定合同的遵守情况 - TheClass 将在映射器返回的 BasketModel 上调用 FormatModel。如果您需要在测试中复制一些实现(同样,通常不鼓励这样做),您可以使用When..Do

[Test]
public void FormatModel()
{
    // Arrange
    var booking = new Booking { CurrencyCode = "" };
    var expectedModel = Substitute.For<IBasketModel>();
    expectedModel
       .When(x => x.FormatModel(Arg.Any<SomethingHere>()))
       .Do(/* some action */);
    _modelMapper.GetModel(booking).Returns(expectedModel);

    // Act
    var result = theClass.GetModel(booking, null);

    // Assert
    // assertion here that depends on "some action" and result
}

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 2021-01-03
    • 2021-06-10
    • 2018-06-18
    • 1970-01-01
    • 2022-01-16
    • 2014-01-31
    相关资源
    最近更新 更多