MOQ - 验证异常被抛出

时间:2013-04-17 06:52:39

标签: c# unit-testing moq

我使用MOQ框架进行测试。 我有一个场景,我期望抛出一个错误异常。 我如何验证它被抛出?

public void Koko(List<string?> list) 
{ 
   foreach(string? str in list) 
   { 
        if (str != null) someProperty.Foo(str); 
        else throw new FormatException(); 
   } 
} 

提前致谢。

7 个答案:

答案 0 :(得分:26)

如果你想验证抛出异常(通过你自己的代码),那么Moq不是你选择的工具。 只需使用其中一个单元测试框架即可。

<强>的xUnit / NUnit的:

Assert.Throws<SomeException>(() => foo.Bar());

流利断言:

Action act = () => foo.Bar();
act.ShouldThrow<SomeException>();

http://fluentassertions.codeplex.com/documentation

http://www.nunit.org/index.php?p=exceptionAsserts&r=2.6.2

答案 1 :(得分:23)

我可能会误读你的意图,但据我所知,没有必要对模拟做任何事情来测试异常是否被抛出。

看起来你有一个带有方法Foo的类,它接受一个字符串 - 让我们调用这个InnerClass

public class InnerClass {
    public virtual void Foo(string str) {
         // do something with the string
    }
}

和一个包含InnerClass作为属性的类(someProperty),它有一个成员Koko,它采用List&lt; string&gt;作为参数

public class OuterClass {

    private readonly InnerClass someProperty;

    public OuterClass(InnerClass someProperty) {
        this.someProperty = someProperty;
    }

    public void Koko(List<string> list) {
         foreach (var str in list) {
              if (str != null)
                   someProperty.Foo(str);
              else
                   throw new FormatException();
          }
    } 
}

注意:我无法获取List&lt; string?&gt;编译 - 告诉我底层类型(字符串)必须是不可为空的。 AFAIK,只需要使值类型可以为空,引用类型可以隐式为空。

看起来你想要测试一下,如果你传入一个字符串列表,其中任何一个字符串都是null,抛出FormatException。

如果是这样,那么MOQ的唯一原因就是让我们不要担心InnerClass功能。 Foo是一种方法,因此,除非我们使用严格的模拟,否则我们可以创建一个没有其他设置的InnerClass模拟。

有一个属性[ExpectedException],我们可以用它来标记我们的测试,以验证是否已抛出异常。

[TestMethod]
[ExpectedException(typeof(FormatException))]
public void ExceptionThrown() {

    var list = new List<string>() {
        "Abel",
        "Baker",
        null,
        "Charlie"
    };

    var outer = new OuterClass(new Mock<InnerClass>().Object);
    outer.Koko(list);

}

如果抛出FormatException,则此测试将通过,如果不抛出则会失败。

答案 2 :(得分:11)

请阅读Introduction to Moq。以下是在调用InvalidOperationException方法时设置DoSomething投掷的方法:

mock.Setup(foo => foo.DoSomething()).Throws<InvalidOperationException>();

然后只需验证方法是否被调用。如果它被调用,则引发异常

mock.Verify(foo => foo.DoSomething());

答案 3 :(得分:9)

您可以使用NUnit Asserts测试是否抛出了异常:

Assert.That(() => testObject.methodToTest(), Throws.TypeOf<FaultException>());

答案 4 :(得分:7)

一个老问题,但没有源代码实际显示解决方案是什么,所以这就是我所做的:

var correctExceptionThrown = false;

try
{
    _myClass.DoSomething(x);
}
catch (Exception ex)
{
    if (ex.Message == "Expected message")
        correctExceptionThrown = true;
}                    

Assert.IsTrue(correctExceptionThrown);

注意而不是检查消息,您可以捕获特定类型的异常(通常更可取)。

答案 5 :(得分:5)

通读这些答案,我意识到还有另一种使用NUnit的方法。以下内容从异常中获取异常文本并验证错误消息文本。

var ex = Assert.Throws<SomeException>(() => foo.Bar());
Assert.That(ex.Message, Is.EqualTo("Expected exception text");

而且我无法使用最新版本的NUnit来使装饰/属性语法(上面的AlanT回答)起作用-不知道为什么,但是无论我尝试做什么,它都会抱怨。

答案 6 :(得分:1)

好的,所以我通过以下方式解决了它。

由于异常中断了我的测试,我将方法调用放在了try-catch中的Because块中。

然后我可以使用简单的验证。

感谢所有帮助者......