1

I m using NUnit, I have following code which will be tested.

public class StudentPresenter
{
    IView myview;
    Repository myrepo;
    public StudentPresenter(IView vw, Data.Repository rep)
    {
        this.myview = vw;
        this.myrepo = rep;
        this.myview.ButtonClick += myview_ButtonClick;
    }

    public void myview_ButtonClick()
    {
        try
        {
         var d = this.myrepo.GetById(int.Parse(myview.GivenId));
         this.myview.GetStudent(d);
        }
        catch(Exception e)
        {
        }

    }
}


I need to test myview_ButonClick()
Lets suppose I will test this method and it will throw exception if myview.GivenId is null?
So I write unit test as below:

[Test]       
public void Button1Click_NullText_ThrowException()
{
    var mock = Substitute.For<IView>();
    StudentPresenter sp = new StudentPresenter(mock, repo);
    mock.GivenId = string.Empty;
    Assert.Throws<Exception>(()=>sp.myview_ButtonClick());
}


But test failed.. Why? (becouse no throw in my catch block). But I dont want to throw anything, I just want that it has to ability to catch. So is it possible to test?

Michael Riva
  • 531
  • 1
  • 7
  • 16
  • 2
    The above question is the same as yours in essence: you don't have to test that a part of your unit works as it should, you have to test the entirety of the unit. Note that catching an exception (and definitely a general `Exception`) and not doing anything is bad practice. – Jeroen Vannevel Apr 30 '14 at 00:16

2 Answers2

4

You cannot have a unit test that checks if a code block has a "catch" block. The only way to (indirectly) do it would be to test that the test does not throw when given input that would normally cause it to throw.

NUnit has a DoesNotThrow assert that should be useful here.

Of course, that's no guarantee of the existence of a try/catch, but its about the best you can do.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • 2
    +1. Note that if someone really want to check for presence of `try`/`catch` in a method it is possible to get IL of the method and parse it... but it would be really stretch to call it unit test at that point. – Alexei Levenkov Apr 30 '14 at 00:32
  • @AlexeiLevenkov: with Roslyn it would be *somewhat* feasible to do it (actually, it would be rather easy) but it would be rather dirty. And really serves no use – Jeroen Vannevel Apr 30 '14 at 00:34
  • @AlexeiLevenkov sounds good, can you give an example? it will be awsome if you do. – Michael Riva Apr 30 '14 at 00:34
  • @AlexeiLevenkov, hadn't though of checking the IL, as you say that wouldn't really be a *unit* test. In fact, I'm not really sure what kind of test that would be. Perhaps you have invented a new one! – BradleyDotNET Apr 30 '14 at 00:36
  • @AlexeiLevenkov yes yes please I realy wonder, i need an example :) – Michael Riva Apr 30 '14 at 00:39
  • 2
    @MichaelRiva I'm not sure you understand the concept of a *unit* test. Unit tests test that a function behaves as expected given different input/state. You shouldn't be checking for a specific line of code (or keyword), you should be checking if the behavior is correct. To a unit test, a function is a "black box" and all that matters is correct output given certain input. I'm sure seeing the IL code would be interesting, but you need to understand the **you shouldn't actually do this** piece of it as well. – BradleyDotNET Apr 30 '14 at 00:43
  • @MichaelRiva - one option is to look at ILSpy for inspiration. To get raw IL (bytes) - [MethodInfo.GetMethodBody](http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody%28v=vs.110%29.aspx) – Alexei Levenkov Apr 30 '14 at 01:24
  • @BradleyDotNET - it is exactly what "code analysis" in VS doing - not really "test". It may be useful for some sort of automatic validation of third party code i.e. to verify using (or not using) some particular API - may be at [acceptance](http://en.wikipedia.org/wiki/Acceptance_testing) level of tests.. – Alexei Levenkov Apr 30 '14 at 01:29
2

myview_ButtonClick() catches all exceptions, and so it will never throw an exception that could be detected from outside the method, hence your test fails.

If you want to catch the exception, do something with it, and then throw it in order for a caller to catch it, or the test to pass, then simply

catch (Exception e)
{
    //actions....
    throw;
}

Bear in mind too that catching all exceptions is rarely a good idea. The calling code will continue oblivious to the exception state, and this could cause untold problems down the line, which could be a nightmare to debug and track down.

dyson
  • 866
  • 6
  • 12