如何测试方法是否在特定输入上引发异常

时间:2015-03-23 13:36:11

标签: c# asp.net-mvc nunit nsubstitute

在下面的方法中,当model.test为空时,我希望此方法抛出异常。

public bool Create(Test model)
{
    if (model.test == null)
    {
        throw new InvalidOperationException("nanana.");

    }
    try
    {
        return true;
    }
    catch (InvalidOperationException ex) { throw; }
}

这是我目前的测试:

[Test]
public void Only_one_property_should_be_set()
{
    var rep  =  Substitute.For<ITestRepository>();

    var x = rep.Create(model.ToEntity());

    Assert.Throws<InvalidOperationException>(() => rep.Create(model.ToEntity()));
}

它不起作用,因为x总是返回false。

我可以直接替换TestRepository,但之后我会将项目插入到数据库中,我不想这样做。如何在不将项插入数据库的情况下使用NUnit和NSubstitute测试存储库异常?

1 个答案:

答案 0 :(得分:4)

您正在做的事情存在几个问题。正如评论中已经说过的那样,模拟/替换你试图测试的课程通常是一个坏主意。模拟和替换用于允许您通过测试代码控制逻辑流程,而不是替换测试中的代码。

由于您所展示的代码除了模型类之外没有任何依赖关系,因此在这种情况下根本没有理由使用替代品。如果您的代码看起来像这样(伪代码)

,您将使用替换
if(model.Test == null) {
   throw someException
}
_someDependency->Create(model.Value1, model.Value2, model.Test)

在上面的代码中,_someDependency是一些底层数据库交互类,它已经通过它的构造函数注入到存储库中。然后,您可以为_someDependency创建替换,以便影响Create方法的流程,或验证与依赖项的交互。

就目前的方法测试方法而言,没有理由不能传递具有test==null的模型。该方法中的逻辑流程是这样的:如果该测试失败,您将不会期望将数据写入数据库,这是检查的关键。所以,你的测试可能看起来像这样:

[Test]
public void CreateShouldThrowIfModelTestIsNull()
{
    var testModel = model.ToEntity();

    var sut  =  new TestRepository();

    testModel.test = null;

    try {
        sutCreate(testModel);
        Assert.Fail("Expected Exception");
    } catch(InvalidOperationException ex) {
        Assert.AreEqual("nanana.", ex.Message);
    }
}