我使用MOQ框架进行测试。 我有一个场景,我期望抛出一个错误异常。 我如何验证它被抛出?
public void Koko(List<string?> list)
{
foreach(string? str in list)
{
if (str != null) someProperty.Foo(str);
else throw new FormatException();
}
}
提前致谢。
答案 0 :(得分:26)
如果你想验证抛出异常(通过你自己的代码),那么Moq不是你选择的工具。 只需使用其中一个单元测试框架即可。
<强>的xUnit / NUnit的:强>
Assert.Throws<SomeException>(() => foo.Bar());
流利断言:
Action act = () => foo.Bar();
act.ShouldThrow<SomeException>();
答案 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块中。
然后我可以使用简单的验证。
感谢所有帮助者......