使用Moq和MSTest测试异常的正确方法

问题描述:

对于Moq与MsTest的行为有些困惑.

A little confusion as to the behaviour of Moq with MsTest.

这不是如何测试"的问题.或我该如何断言?",这是查看MoQ的工作原理的便笺簿,因此请不要关注异常类型等.

This is not a question of "How do I test?" or "How do I assert?", this is a scratch pad to see how MoQ works so don't focus on the exception type etc.

我认为一个更好的问题可能是=>"Moq投掷行为是否类似于MsTest ExpectedExceptionAttribute?"也就是说,他们期望测试或SUT中有异常吗?

I think a better question may be => "Does Moq Throws<> behave similar to MsTest ExpectedExceptionAttribute?" That is, they're expecting an exception in the test or the SUT?

我想知道与MsTest一起使用的MoQ"Throws"是如何工作的.最好不使用MsTest预期的异常属性吗?在测试中执行try..catch更好吗?我对此还有其他疑问.

I'd like to know just how MoQ "Throws" works when used with MsTest. Is it better to not use the MsTest expected exception attribute? Is it better to perform a try..catch within the test? I have a few more questions surrounding this.

我正在模拟数据库调用,当发生错误时,我想返回零(0).

I am Mocking a database call and when an error occurs I would like to return zero (0).

TestMethod具有MsTest异常属性,而Moq引发throws异常.仅当我在SaveCart方法中引发异常时才起作用,而当我返回零时则无效.

The TestMethod is straight forward with the MsTest exception attribute, and the throws exception with Moq. It only works when I throw an exception within the SaveCart method and not when I return zero.

我想了解基本行为,因为感觉好像我不应该,也不想在SaveCart方法内引发异常.

I would like to understand the underlying behaviour because it feels as though I shouldn't, nor want to throw an exception within the SaveCart method.

这是正在测试的问题:

[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void CartRepoSaveCartExceptionShouldReturnZero()
{
     _cartDatabaseMock.Setup(c => c.SaveCart(_cart))
                                   .Throws<ApplicationException>();

    var result = _cartRepository.SaveCart(_cart);

    Assert.AreEqual(result, _cartSaveExceptionValue);
}

这是基本的SaveCart,它不会引发异常而导致测试失败:

Here is the basic SaveCart which does NOT throw an exception causing the test to fail:

public long SaveCart(Cart cart )
{
    long returnValue;

    try
    {
        returnValue = _cartDatabase.SaveCart(cart);
    }
    catch (Exception)
    {
        return 0;
    }
    return returnValue;
}

这是一个基本的SaveCart,测试可以在这里进行,因为它会抛出异常:

Here is a basic SaveCart where the test works because it's throwing an exception:

public long SaveCart(Cart cart )
{
    long returnValue;

    try
    {
        returnValue = _cartDatabase.SaveCart(cart);
    }
    catch (Exception)
    {
        throw new ApplicationException();
    }
    return returnValue;
}

如果对问题的解释不够清楚,可以随意提出一个更好的标题.

Feel free to suggest a better title for the question if it doesn't quite explain it clearly.

您是正确的-第二个测试"SaveCart"之所以起作用,是因为它引发了异常,而第一个测试却因为您变为0而失败.答案,我相信您已经知道所有这一切.如果您要询问该行为它是如何在您的第一次测试中失败的……它是这样的:

You are right - the second test "SaveCart" works because it's throwing an exception and the the first test fail because you are turning 0. From your response to previous answers, I am sure you already know all of this. If you are asking for the behavior how it failed your first test... it goes like this:

  1. SaveCart被称为
  2. 它返回一个异常(您的最小起订量的结果)
  3. 您的try catch捕获到异常(您是故意这样做的,以改变结果)
  4. 您的try catch返回0(现在您打算更改结果为0)
  5. Assert针对_cartSaveExceptionValue检查您的结果
  6. 您将获得失败测试,​​声明与此内容类似:消息:Assert.AreEqual失败.预期.实际."

如果您要再次检查...,可以尝试以下测试

If you want to double check this... you can try the following test

  1. 注释[ExpectedException(typeof())]
  2. 将Assert.AreEqual(result,_cartSaveExceptionValue)更改为Assert.AreEqual(result,0);
  3. 该测试应该通过,因为您正在将结果"(aka 0)与0进行比较

我希望这能回答您的问题.

I hope this answer your question.