A little confusion as to the behaviour of Moq with MsTest.
Edit: 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.
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?
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.
I am Mocking a database call and when an error occurs I would like to return zero (0).
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.
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.
Here is the Test under question:
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void CartRepoSaveCartExceptionShouldReturnZero()
{
_cartDatabaseMock.Setup(c => c.SaveCart(_cart))
.Throws<ApplicationException>();
var result = _cartRepository.SaveCart(_cart);
Assert.AreEqual(result, _cartSaveExceptionValue);
}
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;
}
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.
You should use ExpectedExceptionAttribute when the unit under test throws an exception.
In your first example the method didn't throw any exception therefore the test failed.
Since your method under test doesn't throw any exception you don't need to use this attribute at all...(just verify the return value in this scenario)
When you want to verify that exception was thrown and you want to verify that some additional operations occurred, use the following pattern:
[TestMethod]
[ExpectedException(typeof(<The specific exception>))]
public void FooTest()
{
//arrange
try
{
// act
}
catch(<the specific exception>)
{
// some asserts
throw;
}
}
The above snippet will failed if:
BTW, since your catch in the method is no Exception
instead of ApplicationException
, I offer you to change the setup to:
_cartDatabaseMock.Setup(c => c.SaveCart(_cart)).Throws<Exception>();
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:
If you want to double check this... you can try the following test
I hope this answer your question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With