108

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.

Liam
  • 27,717
  • 28
  • 128
  • 190
CuriousGeorge
  • 1,105
  • 2
  • 7
  • 6

9 Answers9

179

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)

Rob Levine
  • 40,328
  • 13
  • 85
  • 111
28

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.

Clarkeye
  • 889
  • 8
  • 9
  • 1
    The explicit DoesNotThrow is nice. If you're accustomed to seeing Assert.* in a test, you might think the other guy was lazy and forgot. – Matt Beckman Jun 11 '14 at 18:04
  • 1
    Is there any equivalent for it in vstest or mstest? – Dan Csharpster Mar 12 '15 at 18:40
  • 2
    @DanCsharpster, I don't think there is, at least in MSTest - when I've needed this functionality in MSTest in the past, I've done something like this: `public class TestBase { //believe me, I don't like this anymore than you do. protected void AssertDoesNotThrow(Action action, string message) { try { action(); } catch (Exception) { Assert.Fail(message); } } }` – Clarkeye Mar 27 '15 at 11:19
  • @Clarkeye, that's an interesting idea. Thanks! Hopefully, they'll learn to copy NUnit better, in future versions. I also thought about writing an adapter between vstest and NUnit. – Dan Csharpster Mar 27 '15 at 13:13
  • @DanCsharpster, one thing you might want to have a look at is fluent assertions, which has nice support for ShouldThrow and ShouldNotThrow: https://github.com/dennisdoomen/fluentassertions/wiki#exceptions. The docs say it is compatible with MSTest (although I've only used it with XUnit and NUnit). Might not do everything you want, but you can mix it with the MSTest assertions anyway. – Clarkeye Mar 28 '15 at 13:20
  • In NUnit is there a way to do this using Assert.That rather than Assert.DoesNotThrow...? – bytedev Apr 20 '17 at 10:09
  • @nashwan, the only thing I could think would be to use a try...catch with a boolean value you can set directly after the code you want to test, eg: bool didNotThrow = false try { ThisCodeShouldNotThrow(); didNotThrow = true; } catch {} Assert.That(didNotThrow); It's a bit of any ugly approach though! Is there a reason you wouldn't use Assert.DoesNotThrow? – Clarkeye Apr 21 '17 at 12:35
  • @Clarkeye only reason I wondered cos Assert.That seems to have equivalents for nearly everything. But DoesNotThrow() is good, I've used it before :-) – bytedev Apr 25 '17 at 16:49
  • Example usage; **Assert.DoesNotThrow(() => YourMethod());** – Furkan Öztürk Dec 05 '20 at 11:47
12

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);
        }
    }
}
JJS
  • 6,431
  • 1
  • 54
  • 70
  • @Remco Beurskens - adding a general catch { } at the end of NoExceptionThrown will suppress other errors, which is not an intended consequence of the method. This is not a general purpose method to suppress all Exceptions. It is intended to fail only when an exception of the known type IS thrown. – JJS Jul 25 '19 at 11:40
  • 3
    This is super-old now, but `Assert` has a singleton property accessor, `That` which one can use as a hook for extension methods. It might be neater, and more discoverable, to have `Assert.That.DoesNotThrow()` rather than `AssertEx.DoesNotThrow()`. This is just an opinion. – Richard Hauer Oct 30 '19 at 00:54
11

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.

Community
  • 1
  • 1
k.m
  • 30,794
  • 10
  • 62
  • 86
  • 13
    -1 I can think of positive functionality that requires and exception not be thrown. For one - method whose job it is to handle exceptions, log them and take action - without throwing the exception further. You make a good general point - but then speak in the _absolute_ as if it is always true. – Rob Levine Feb 23 '12 at 20:19
  • @RobLevine: what happens when your example throws while logging? Do you assert that it doesn't and have a test for that? That was my whole point. I didn't mean to sound "religious" (nor I understand reason for downvote), but asserting that something *doesn't happen*, in general is **very** counterproductive. You usually want opposite, assert your code *does something*. It's just plain easier. – k.m Feb 24 '12 at 01:43
  • I do understand your point - and it is good _general_ advice. The trouble is, the moment you start with absolutes, you damage the core point. If the nature of the code under test is to _prevent_ an exception being thrown, then it is a _positive_ assertion to make sure none is thrown. Your overall point is a good one, _in the general case_, but I think it was the way you framed it which made me feel that overall it was unhelpful advice. The -1 was a bit harsh - I changed my mind a few minutes later but it won't let me +1 unless you edit your post again. Sorry about that. – Rob Levine Feb 24 '12 at 10:13
  • 3
    @RobLevine: I understand your example and do realize you write tests in such cases. Yet as you noticed, my point indeed was about more general practice - so to speak, testing for what your code is supposed to do versus testing for what your code doesn't do. I've rephrased my post a bit, so that my point is more clear and closer to what I had in mind. Also gives you an opportunity to reconsider your vote. Thanks for clarification and sorry for delayed response. – k.m Feb 26 '12 at 19:02
  • 5
    downvote removed - I'll not be so trigger happy on the down-vote next time! – Rob Levine Feb 27 '12 at 11:05
  • 5
    In our project we have htmlvalidator class, that throws exceptions if html is not valid. For example when user input (using console) javascript in rich combo. So in my case code what my code do is to not throw exception (white list approach) and I need to test for that. – Machet Oct 29 '14 at 11:22
  • I'm conflicted about this answer. I'm writing tests for a seekable version of [this ConcatenatedStream class](http://stackoverflow.com/a/3879231/247702), one of them is `Setting_the_position_to_0_with_zero_backing_streams_should_succeed()`. I could instead test that the position is still 0 after setting it to 0, in other words verify that an action succeeded. But I'm not sure if this holds true for *all* unit tests of the "shouldn't throw" type. – user247702 Apr 08 '15 at 11:52
  • 2
    Disagree with this answer. Testing for the absence of something sometimes under a certain scenario can be a valid test. – bytedev Dec 08 '17 at 14:11
  • @k.m regarding your statement "asserting that something doesn't happen, in general is very counterproductive", consider the following - I have a SUT with a void return method, which given a certain argument, should throw. I can write that test, making the assertion it throws in this case, however given that it has a void return type, I cannot write a test with an actual assertion to check it is working; the best I can do is verify that all the dependency methods are hit. I found the logical course was to write this test, verifying dependencies, with the assertion being that it doesn't throw. – Jake Stokes Apr 11 '18 at 12:27
  • Without making the assertion that this particular SUT method doesn't throw when the inputs are indeed valid, I am leaving a huge gap in my unit tests. What are your thoughts? – Jake Stokes Apr 11 '18 at 12:29
  • @k.m Consider you have a validator class which throws certain custom exceptions when the input is invalid. So is it a crime to write couple of tests which feed valid inputs and all what the tests will do is assert for 'does not throw'? – Ε Г И І И О Feb 26 '19 at 05:14
  • Disagree as the answer is too absolute. In general, it's true that one should test positively for things that we expect. But there are some cases in which we need to test for the opposite. It's valid logic to want to know that a certain important condition does not throw an exception, when another related condition might. And its good to cover this with a test. – DvS Sep 23 '19 at 20:16
4

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

    }
jleach
  • 7,410
  • 3
  • 33
  • 60
  • It’s not the same. If your code throws, no assertion will be hit and your test run will fail. You want to hook into the testing framework by asserting a condition. – DvS Sep 23 '19 at 21:31
2

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);
DaveVentura
  • 612
  • 5
  • 19
1

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.

Jess
  • 23,901
  • 21
  • 124
  • 145
  • 2
    the OP is asking for an no exception. – Daniel A. White May 31 '19 at 13:47
  • I'm gonna leave this answer here. I found this question while searching google for how to test for exceptions and this answer I think needs to be here. The OP had their question answered 7 years ago. Even the link to the other answer I think is helpful. – Jess Jun 03 '19 at 12:45
  • 2
    Good ole Tim. – ruffin Jul 27 '20 at 18:37
0

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())
John Smith
  • 31
  • 4
-1
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);
}

Harshal
  • 45
  • 3