MOQ - verify exception was thrown - c#

I working with MOQ framework for my testing.
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();
}
}

If you want to verify an exception was thrown (by your own code) then Moq is not your tool of choice for that.
Simply use one of the unit test frameworks available.
Xunit/NUnit:
Assert.Throws<SomeException>(() => foo.Bar());
Fluent Assertions:
Action act = () => foo.Bar();
act.Should().Throw<SomeException>();
https://fluentassertions.com/introduction
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.
It looks like you have a class with a method Foo that takes a string - lets call this 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
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. AFAIK, one only needs to make value types nullable, reference types are implicitly nullable.
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.
If so, then the only reason for a MOQ is to release us from worrying about the InnerClass functionality. Foo is a method, so, unless we are using strict mocks, we can just create an InnerClass mock with no other setup.
There is an attribute [ExpectedException] with which we can tag our test to verify that the exception has been thrown.
[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.

Reading through these answers I realized there is yet another way to do this using 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.

Please read this Introduction to Moq. Here is the way to setup InvalidOperationException throwing when DoSomething method is invoked:
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());

You can test that an Exception is thrown using 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).

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.
Then I could use a simple Verify.
Thanks to all helpers...

Related

XUnit and MSTest with ExpectedException Returning Different Results

I have a project that is using a yield return and do not understand why XUnit is failing to catch an exception in my unit test while MSTest is passing.
Here is my dummy code.
The bizarre thing is that if I take my private method, EnumerableYieldReturn, and put that logic directly in my public method, YieldReturnList, the outcomes flip with the XUnit test passing and the MSTest failing.
[TestClass]
public class MSTestRunner
{
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void MSTestUsingExpectedException()
{
var sut = new YieldReturn();
sut.YieldReturnList(null);
}
}
public class XUnitRunner
{
[Fact]
[ExpectedException(typeof(ArgumentException))]
public void XUnitUsingExpectedException()
{
var sut = new YieldReturn();
sut.YieldReturnList(null);
}
}
public class YieldReturn
{
public IEnumerable<string> YieldReturnList(int? value)
{
if (value == null)
throw new ArgumentException();
return EnumerableYieldReturn((int)value);
}
private IEnumerable<string> EnumerableYieldReturn(int value)
{
var returnList = new List<string>() { "1", "2", "3" };
for (int i = 0; i < value; i++)
{
yield return returnList[i];
}
}
}
I can get them both to pass by assigning the return object from sut.YieldReturnList and attempting to iterate through it but that doesn't explain why one framework is passing and the other is failing...
"xUnit.net has done away with the ExpectedException attribute in favor of Assert.Throws." from https://xunit.github.io/docs/comparisons.html.
The reason for the flip of results is that the exception is no longer thrown so:
MSTest: expects the exception because it uses the attribute, and therefore fails because it doesn't get the exception
XUnit: ignores the expect exception attribute because the framework doesn't use it, and therefore passes because an exception didn't cause the test to fail.
The reason the exception is no longer thrown if you change the methods is more complicated but it basically has to do with creating a state machine for methods that use the yield key word. Currently your public method doesn't use the yield key word directly so it is treated like a normal function and therefore executes the null check and throws the exception as soon as the method is called. Moving the yield key word to the public method makes it a lazy state machine so it doesn't execute the null check to throw the exception until you start to iterate the IEnumerable.

how to pass types into test method

How can I pass types into my unit tests?
public void MethodUnderTest()
{
try
{
var businessService = _businessService.DoWork();
}
catch (SomeException exception)
{
//do some stuff
}
catch (SomeOtherException exception)
{
//do other stuff
}
}
My unit test should be something like this:
[TestCase(typeof(SomeException))]
[TestCase(typeof(SomeOtherException))]
public void UnitTest(Exception exception)
{
_businessService.Setup(x=>x.DoWork).Throws.InstanceOf<exception>();
//verify that when we called DoWork, that the logic inside of one of the catches was executed
}
One way this can be implemented would be, by utilizing inferred generics ..
you will have a test case source in your test fixture.
public static List< Exception > Exceptions => new List< Exception >
{
new InvalidOperationException(),
new OverflowException()
};
and then modify your unit test method as :
[Test]
[TestCaseSource(nameof( Exceptions ))]
public void UnitTest<T>( T exception ) where T : Exception, new(){
_businessService.Setup(x=>x.DoWork).Throws.InstanceOf<T>();
//verify that when we called DoWork, that the logic inside of one of the catches was executed
}
Then the code would infer the types from the instance of the exceptions in the test case source. I can't think of a way to do this with out instantiating the exceptions ...
You haven't said what you have tried that didn't work. On the surface, it appears easy enough, but perhaps I don't understand what you want to do.
The example unit test you show is incorrect. It takes an Exception as an argument, but you are giving it a Type. Based on your title, the test method should accept a type. Then do something like...
[TestCase(typeof(SomeException))]
[TestCase(typeof(SomeOtherException))]
public void UnitTest(Type exceptionType)
{
Assert.That(()=>_businessService.Setup(x=>x.DoWork),
Throws.InstanceOf(exceptionType));
}
```
Did I misunderstand the problem?

Is there a short and simple way for checking variable/property values?

I wonder whether there is a short and simple way for checking whether variable/property values match some condition?
Currently one of the most popular line in my code is similar to this one:
if (string.IsNullOrWhiteSpace(someFileName))
{
throw new NullReferenceException("'someFileName' must not be null.");
}
then the exception gets logged in the catch part and the execution continues and so on.
I don't like writing this line all over the place and just changing the variable name. It would be great if one could write something like this:
Assert.IsNotNullOrWhiteSpace(someFileName);
and it threw an exception saying that "{my variable} must not be null" with maybe some additional information like the parent class etc. that would help you to debug the code if you only have the logs available.
The problem with writing such a utility class that I encountered was that the thrown exception had of course the wrong stack trace like it happened in the utility method and not inside the method that called the assertion function.
This kind of value checking is required to especially work at runtime because I most of the time check user input like settings, paths, inputs etc.
EDIT:
I think I should have given an example of what I try to achieve:
public class FileExtractor {
public Form MainForm { get; set; }
public void ExtractFile(string fileName) {
Assert.IsNotNullOrWhiteSpace(fileName);
Assert.IsNotNull(MainForm);
// ...
}
}
and the let's call it Assert library should do this:
public static Assert {
public static void IsNotNullOrWhiteSpace(this string value) {
if (string.IsNullOrWhiteSpace(value)) {
// throw an exception like it occured in the ExtractFile
// the message should contain a hint like: "fileName must not be null"
}
}
public static void IsNotNull(this object value) {
if (value == null) {
// throw an excaption like it occured in the ExtractFile,
// the messagge should contain a hint like: "FileExtractor.MainForm must not be null."
}
}
EDIT-2
#CodeCaster - unfortunately I cannot not use C# 6 yet.
After some research and inspirated by two other questions here on stackoverflow
How to get Property Value from MemberExpression without .Compile()?
and
get name of a variable or parameter
I came up with this so far:
namespace ExceptionTest
{
class Program
{
static void Main(string[] args)
{
object test = null;
Assert.IsNotNull(() => test);
}
}
static class Assert
{
public static void IsNotNull<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpr = expression.Body as MemberExpression;
var constExpr = memberExpr.Expression as ConstantExpression;
var value = (memberExpr.Member as FieldInfo).GetValue(constExpr.Value);
if (value == null)
{
throw new ArgumentNullException(memberExpr.Member.Name);
}
}
}
}
It almost does what I need. The last thing is to modify the stack trace so that it points to the Main method and not to the IsNotNull
You could use Debug Methods (http://msdn.microsoft.com/en-us/library/System.Diagnostics.Debug_methods%28v=vs.110%29.aspx), which however only work when compiling in debug mode.
Maybe Debug.WriteLineIf(Boolean, String) does what you need?
http://msdn.microsoft.com/en-us/library/y94y4370%28v=vs.110%29.aspx
How about applying attributes to the properties
http://msdn.microsoft.com/en-us/library/dd901590(VS.95).aspx
I think that you should try with Fody library library. For null-guards there is a package that you can find here. All libs are available via Nuget.
Fody is some kind AOP library that uses "weaving" technique to manipulate IL of an assembly and inject additional code.
So NullReferenceExcpetion (or maybe NullArgumentException) will be thrown exactly from your method.
Example from GitHub:
Your code
public void SomeMethod(string arg)
{
// throws ArgumentNullException if arg is null.
}
public void AnotherMethod([AllowNull] string arg)
{
// arg may be null here
}
What gets complied
public void SomeMethod(string arg)
{
if (arg == null)
{
throw new ArgumentNullException("arg");
}
}
public void AnotherMethod(string arg)
{
}

How to expect an exception and still pass the test?

I have this:
Expect.Once.On( someObj ).Method( "SomeMethod" )
.With(1) // correct value is 2, I want this to fail
.Will( Throw.Exception( new Exception() ) );
An exception is thrown by nmock when it detects that I put 1 instead of 2. However, the test is failing (red) instead of passing. How to make this test pass, even though I'm expecting an exception?
If you're using NUnit then you can do:
Assert.Throws<Exception>(() => { someObj.SomeMethod(1); });
You can also decorate the test with an ExpectedException attribute, although that will cause the test to pass if any Exception is thrown, rather than just the statement you want to test.
EDIT: If you're using MSTest, as far as I know, you can only use attributes to expect exceptions i.e.
[ExpectedException(typeof(Exception)]
public void TestMethod() { ... }
You should consider throwing a more specific exception type from your mock and expecting that type instead of a plain Exception.
You could also define your own method to replicate the NUnit functionality:
public static class ExceptionAssert
{
public static void Throws<T>(Action act) where T : Exception
{
try
{
act();
}
catch (T ex)
{
return;
}
catch (Exception ex)
{
Assert.Fail(string.Format("Unexpected exception of type {0} thrown", ex.GetType().Name));
}
Assert.Fail(string.Format("Expected exception of type {0}", typeof(T).Name));
}
}
[ExpectedException (typeof(Exception))]
Edit: thanks, don't have the studio right now and was not 100% sure about the syntax.

NUnit's TestCustomException doesn't care about the exception type

If I want to test that a method throws an exception of a particular type, NUnit's ExpectedException attribute doesn't care about the actual type; if I throw a generic Exception before the method call, the test passes:
[Test, ExpectedException(typeof(TestCustomException))]
public void FirstOnEmptyEnumerable()
{
throw new Exception(); // with this, the test should fail, but it doesn't
this.emptyEnumerable.First(new TestCustomException());
}
If I want to check that the test throws the exact exception type, I have to do something manual like this:
[Test]
public void FirstOnEmptyEnumerable()
{
try
{
throw new Exception(); // now the test fails correctly.
this.emptyEnumerable.First(new TestCustomException());
}
catch (TestCustomException)
{
return;
}
Assert.Fail("Exception not thrown.");
}
Am I missing something?
I've never used ExpectedException, so I don't have any experience to share on this. An option is to Assert that it Throws directly inside the test. Something like this:
[Test]
public void FirstOnEmptyEnumerable()
{
Assert.Throws<TestCustomException>(() => this.emptyEnumerable.First(new TestCustomException()));
}
I find this approach more readable as you test for the exception exactly where you expect it to happen instead of saying "somewhere inside this function I except an exception to be thrown".
I always test for the string representation of the exception e.g.:
[Test, ExpectedException("Your.Namespace.TestCustomException")]
public void FirstOnEmptyEnumerable()
{
throw new Exception(); // with this, the test should fail, but it doesn't
this.emptyEnumerable.First(new TestCustomException());
}
Which seems to work fine for me.
If you want to use the ExpectedException(string) signature, the best practice would be to use typeof(Exception).Name and typeof(Exception).Namespace

Categories

Resources