How do I check "no exception occurred" in my MSTest unit test?

C#Unit TestingExceptionMstest

C# Problem Overview


I'm writing a unit test for this one method which returns "void". I would like to have one case that the test passes when there is no exception thrown. How do I write that in C#?

Assert.IsTrue(????)

(My guess is this is how I should check, but what goes into "???")

I hope my question is clear enough.

C# Solutions


Solution 1 - C#

Your unit test will fail anyway if an exception is thrown - you don't need to put in a special assert.

This is one of the few scenarios where you will see unit tests with no assertions at all - the test will implicitly fail if an exception is raised.

However, if you really did want to write an assertion for this - perhaps to be able to catch the exception and report "expected no exception but got this...", you can do this:

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

(the above is an example for NUnit, but the same holds true for MSTest)

Solution 2 - C#

In NUnit, you can use:

Assert.DoesNotThrow(<expression>); 

to assert that your code does not throw an exception. Although the test would fail if an exception is thrown even if there was no Assert around it, the value of this approach is that you can then distinguish between unmet expectations and bugs in your tests, and you have the option of adding a custom message that will be displayed in your test output. A well-worded test output can help you locate errors in your code that have caused a test to fail.

I think it's valid to add tests to ensure that your code is not throwing exceptions; for example, imagine you are validating input and need to convert an incoming string to a long. There may be occasions when the string is null, and this is acceptable, so you want to ensure that the string conversion does not throw an exception. There will therefore be code to handle this occasion, and if you haven't written a test for it you will be missing coverage around an important piece of logic.

Solution 3 - C#

Don't test that something doesn't happen. It's like assuring that code doesn't break. That's sort of implied, we all strive for non-breaking, bug-less code. You want to write tests for that? Why just one method? Don't you want all your methods being tested that they don't throw some exception? Following that road, you'll end up with one extra, dummy, assert-less test for every method in your code base. It brings no value.

Of course, if your requirement is to verify method does catch exceptions, you do test that (or reversing it a bit; test that it does not throw what it is supposed to catch).

However, the general approach/practices remain intact - you don't write tests for some artificial/vague requirements that are out of scope of tested code (and testing that "it works" or "doesn't throw" is usually an example of such - especially in scenario when method's responsibilities are well known).

To put it simple - focus on what your code has to do and test for that.

Solution 4 - C#

This helper class scratched my itch with MSTest. Maybe it can scratch yours also.

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();
    
    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}

Solution 5 - C#

I like to see an Assert.Whatever at the end of each test, just for consistency... without one, can I really be sure there's not supposed to be one there?

For me, this is as simple as putting Assert.IsTrue(true);

I know I didn't accidentally put that code in there, and thus I should be confident enough at quick a skim through that this was as intended.

    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }

Solution 6 - C#

My friend Tim told me about ExpectedException. I really like this b/c it is more succinct, less code, and very explicit that you are testing for an exception.

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

You can read way more about it here: https://stackoverflow.com/questions/19108107/expectedexception-attribute-usage.

Solution 7 - C#

Another way which worked for me is to store it in a variable and check output.

var result = service.Run()
Assert.IsFalse(result.Errors.Any())

Solution 8 - C#

With Xunit you can use this:

var exception = Record.Exception(() =>
 MethodUnderTest());

Assert.Null(exception);

or for async operations

var exception = await Record.ExceptionAsync(async () =>
  await MethodUnderTestAsync());

Assert.Null(exception);

Solution 9 - C#

While most of the other answers here test for a type of exception not occuring, I had to test that "absolutely no type of exception" occurs so this helped

//Act
var exception = Record.Exception(() => callYourMethod());

//Assert
Assert.Null(exception);

Source: https://peterdaugaardrasmussen.com/2019/10/27/xunit-how-to-check-if-a-call-does-not-throw-an-exception/

Solution 10 - C#

using Moq;
using Xunit;

[Fact]
public void UnitTest_DoesNotThrow_Exception()
{
	var builder = new Mock<ISomething>().Object;

	//Act
	var exception = Record.Exception(() => builder.SomeMethod());

	//Assert
	Assert.Null(exception);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCuriousGeorgeView Question on Stackoverflow
Solution 1 - C#Rob LevineView Answer on Stackoverflow
Solution 2 - C#ClarkeyeView Answer on Stackoverflow
Solution 3 - C#k.mView Answer on Stackoverflow
Solution 4 - C#JJSView Answer on Stackoverflow
Solution 5 - C#jleachView Answer on Stackoverflow
Solution 6 - C#JessView Answer on Stackoverflow
Solution 7 - C#John SmithView Answer on Stackoverflow
Solution 8 - C#DaveVenturaView Answer on Stackoverflow
Solution 9 - C#gawkfaceView Answer on Stackoverflow
Solution 10 - C#HarshalView Answer on Stackoverflow