CuriousGeorge
CuriousGeorge

Reputation: 1175

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

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.

Upvotes: 115

Views: 113163

Answers (9)

Harshal
Harshal

Reputation: 51

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);
}

Upvotes: -1

DaveVentura
DaveVentura

Reputation: 760

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);

Upvotes: 7

John Smith
John Smith

Reputation: 31

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())

Upvotes: 0

Jess
Jess

Reputation: 25079

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: ExpectedException Attribute Usage.

Upvotes: 2

jleach
jleach

Reputation: 7792

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

    }

Upvotes: 5

JJS
JJS

Reputation: 6658

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);
        }
    }
}

Upvotes: 12

Clarkeye
Clarkeye

Reputation: 929

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.

Upvotes: 30

k.m
k.m

Reputation: 31454

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.

Upvotes: 11

Rob Levine
Rob Levine

Reputation: 41298

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)

Upvotes: 190

Related Questions