我在我的测试中使用MOQ框架。 有一个场景,我期望会抛出故障异常。 如何验证它是否被抛出?
public void Koko(List<string?> list)
{
foreach(string? str in list)
{
if (str != null) someProperty.Foo(str);
else throw new FormatException();
}
}
我在我的测试中使用MOQ框架。 有一个场景,我期望会抛出故障异常。 如何验证它是否被抛出?
public void Koko(List<string?> list)
{
foreach(string? str in list)
{
if (str != null) someProperty.Foo(str);
else throw new FormatException();
}
}
如果你想验证(你自己的)代码是否抛出了异常,那么Moq不是你首选的工具。 只需使用可用的单元测试框架之一即可。
Xunit/NUnit:
Assert.Throws<SomeException>(() => foo.Bar());
流畅断言:
Action act = () => foo.Bar();
act.Should().Throw<SomeException>();
我可能误解了你的意图,但据我所见,在测试异常被抛出时,没有必要对模拟对象进行任何操作。
看起来你有一个类,其中有一个名为 Foo 的方法,它接受一个字符串参数 - 让我们将其称为 InnerClass。
public class InnerClass {
public virtual void Foo(string str) {
// do something with the string
}
}
包含一个名为someProperty的内部类属性(InnerClass),其中包含一个以List<string>为参数的成员Koko。
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<string?> - 显示其基础类型(string)必须是非空的。据我所知,只有值类型需要可空性,引用类型默认可空。
看起来您想测试如果您传递包含任何null的字符串列表是否会抛出FormatException。
如果是这样,那么MOQ的唯一原因就是可以让我们不用担心InnerClass的功能。Foo是一个方法,所以除非我们使用严格的mocks,否则我们可以只创建一个没有其他设置的InnerClass mock。
有一个属性[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,则此测试将通过,否则将失败。
阅读这些答案后,我意识到还有另一种使用NUnit解决此问题的方法。以下代码从异常中获取异常文本,并验证错误消息文本。
var ex = Assert.Throws<SomeException>(() => foo.Bar());
Assert.That(ex.Message, Is.EqualTo("Expected exception text");
我无法让最新版本的NUnit使用装饰符/属性语法(在上面AlanT的回答中),不知道为什么,但无论我尝试做什么,它都会出错。
但我无法让最新版本的NUnit使用装饰符/属性语法(在AlanT的上面的答案中),不管我尝试什么,它都会抱怨。
DoSomething
方法时抛出InvalidOperationException
的方法:mock.Setup(foo => foo.DoSomething()).Throws<InvalidOperationException>();
那么只需验证方法是否被调用。如果已调用,则会引发异常。
mock.Verify(foo => foo.DoSomething());
你可以使用 NUnit Asserts 测试是否抛出了异常:
Assert.That(() => testObject.methodToTest(), Throws.TypeOf<FaultException>());
这是一个老问题,但实际上没有源代码显示解决方案,所以我做了以下操作:
var correctExceptionThrown = false;
try
{
_myClass.DoSomething(x);
}
catch (Exception ex)
{
if (ex.Message == "Expected message")
correctExceptionThrown = true;
}
Assert.IsTrue(correctExceptionThrown);
注意,与其检查消息,您可以捕获特定类型的异常(通常更可取)。
好的,我是如下方式解决的。
由于异常破环了我的测试,所以我在try-catch中将该方法调用放入"Because"块中。
然后我可以使用简单的验证。
感谢所有的帮助者...
Foo(string)
会抛出ArgumentException
,则应该使用ExpectedException
。 - steve
Bar()
是一个async
方法呢? - LukasFunc<Task> act = () => foo.BarAsync(); await act.Should().ThrowAsync<SomeException>();
- treze... async () => ...
)。 - ksyrium