oli.G
oli.G

Reputation: 1340

Force a .NET test method to fail from the inside

Most of my test methods first try two or three trivial operations which should raise an exception, and then begin the real work. In Java, I would write it like this:

@Test
public void TestSomething() {

    try {
        testedClass.testedMethod(null);
        fail();
    catch (IllegalArgumentException ex) {
        // OK
    }

    // and now let's get to the point ...
    // ...

} 

I wanted to stick with this habit in C#, but it seems there is no way to force a test method to fail. I've been looking a round for a while, but with no luck. Have I missed something?

PS: I know the correct way of testing these situations is this:

[TestMethod]
[ExpectedException(ArgumentNullException)]
public void TestSomethingWithNull() {

    testedClass.TestedMethod(null);

}

[TestMethod]
public void TestSomething() {

   // now the non-trivial stuff...

}

...but, I don't like this. When I have, let's say, 6 test methods in my test class, and each of those tests should start with covering three trivial, one-line situations which should raise an exception, using this approach turns my 6 tests into 18. In a bigger application, this really pollutes my Test Explorer and makes the results more difficult to scan through.

And let's say I want to test a method, whose responsibility is to validate each property of a given instance of some class, and raise a ValidationException if any value is incorrect. That could be easily handled by one TestValidation() test, but with this approach, turns it into:

Imagine you have 20 properties... :)

Of course, if this is the only way to do it, I'll bite.

Upvotes: 2

Views: 3743

Answers (3)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236308

You can use Assert.Fail() or throw NotImplementedException (if method which you are testing is not implemented yet).

But for testing if code throws exception I suggest you to use ExpectedException attribute (if you are stick to MSTest) - test will fail, if exception will not be thrown.

Upvotes: 12

You need

Assert.Fail("Optional Message");

or you can just throw an exception from inside the method

You should also check out the TestCase attribute and TestCaseSource in NUnit. These might greatly simplify your code & testing when you want to pass different parameters to a test.

Upvotes: 4

David Arno
David Arno

Reputation: 43264

The reason why it's advisable to have separate test methods for all the "trivial" stuff is because an Assert.Fail() early in the test method may hide later problems. As you say though, lots of trivial test methods gets unwieldy all too quickly.

Remember though that Asset.Equals (for NUnit at least) can compare arrays. So you can change your tests to something like the following and simulationously test many aspects of the item under test, yet have visibility of all results:

public void TestSomething() 
{
    var result1 = false;
    try 
    {
        testedClass.testedMethod(null);
        result1 = true;
    }
    catch (IllegalArgumentException ex) { }

    var result2 = SomeDetailedTest();

    var expected = new Object[] { false, 42 };
    var actual =  new Object[] { result1, result2 };
    Assert.AreEqual(expected, actual);
} 

Upvotes: 2

Related Questions