简体   繁体   English

MOQ - 验证异常被抛出

[英]MOQ - verify exception was thrown

I working with MOQ framework for my testing. 我使用MOQ框架进行测试。 I have a scenario in which I expect a fault exception to be thrown. 我有一个场景,我期望抛出一个错误异常。 How can I verify it was thrown? 我如何验证它被抛出?

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

Thanks in advance. 提前致谢。

If you want to verify an exception was thrown (by your own code) then Moq is not your tool of choice for that. 如果你想验证抛出异常(通过你自己的代码),那么Moq不是你选择的工具。 Simply use one of the unit test frameworks available. 只需使用其中一个单元测试框架即可。

Xunit/NUnit: 的xUnit / NUnit的:

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

Fluent Assertions: 流利断言:

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

http://fluentassertions.codeplex.com/documentation http://fluentassertions.codeplex.com/documentation

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

I may be mis-reading your intent, but as far as I can see there is no need to do anything to a mock in order to test that the exception has been thrown. 我可能会误读你的意图,但据我所知,没有必要对mock进行任何操作以测试异常是否被抛出。

It looks like you have a class with a method Foo that takes a string - lets call this InnerClass 看起来你有一个带有方法Foo的类,它接受一个字符串 - 让我们调用这个InnerClass

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

and a class which contains an InnerClass as a property (someProperty) which has a member Koko that takes a List<string> as a parameter 和一个包含InnerClass作为属性的类(someProperty),它有一个成员Koko,它将List <string>作为参数

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

NOTE: I cannot get List<string?> to compile - tells me that the underlying type (string) must be non-nullable. 注意:我无法获得List <string?>进行编译 - 告诉我底层类型(字符串)必须是非可空的。 AFAIK, one only needs to make value types nullable, reference types are implicitly nullable. AFAIK,只需要使值类型可以为空,引用类型可以隐式为空。

It looks like you want to test that if you pass in a list of strings where any of them are null that a FormatException is thrown. 看起来你想测试一下,如果你传入一个字符串列表,其中任何一个字符串都是null,抛出FormatException。

If so, then the only reason for a MOQ is to release us from worrying about the InnerClass functionality. 如果是这样,那么MOQ的唯一原因就是让我们不要担心InnerClass功能。 Foo is a method, so, unless we are using strict mocks, we can just create an InnerClass mock with no other setup. Foo是一种方法,因此,除非我们使用严格的模拟,否则我们可以创建一个没有其他设置的InnerClass模拟。

There is an attribute [ExpectedException] with which we can tag our test to verify that the exception has been thrown. 有一个属性[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);

}

This test will pass if a FormatException is thrown and fail if it is not. 如果抛出FormatException,则将通过此测试,否则将失败。

Please read this Introduction to Moq . 请阅读本Moq简介 Here is the way to setup InvalidOperationException throwing when DoSomething method is invoked: 以下是在调用DoSomething方法时设置InvalidOperationException方法:

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

Then simply verify if method was called. 然后只需验证方法是否被调用。 If it was called, then exception was raised 如果它被调用,则引发异常

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

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

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

An old question but no source code actually showing what the solution was, so here's what I did: 一个老问题,但没有源代码实际显示解决方案是什么,所以这就是我做的:

var correctExceptionThrown = false;

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

Assert.IsTrue(correctExceptionThrown);

Note rather than checking the message, you can catch a particular type of exception (generally preferable). 注意而不是检查消息,您可以捕获特定类型的异常(通常更可取)。

Reading through these answers I realized there is yet another way to do this using NUnit. 通过阅读这些答案,我意识到使用NUnit还有另一种方法可以做到这一点。 The following gets the exception text from an exception and verifies the error message text. 以下内容从异常中获取异常文本并验证错误消息文本。

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

And I couldn't get the decoration / attribute syntax to work (AlanT's answer above) using the latest version of NUnit -- not sure why, but it complained no matter what I tried to do. 而且我无法使用最新版本的NUnit来获取装饰/属性语法(AlanT的答案) - 不知道为什么,但无论我怎么做都抱怨它。

Ok so I solved it in the following way. 好的,我以下面的方式解决了它。

Since the exception broke my test I put the method call in the Because block in try-catch. 由于异常打破了我的测试,我将方法调用放在try-catch中的Because块中。

Then I could use a simple Verify. 然后我可以使用简单的验证。

Thanks to all helpers... 感谢所有帮助者......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM