0

I'm writing a unit test, where by I pass in a model and the title field in particular is required.

My test is as follows:

  [TestMethod]
    [ExpectedException(typeof(Exception), "Movie Title is mandatory")]
    public void Create()
    {
        var mc = new MoviesController();

        var model = new Movie
        {
            Cast = new[] { "Scott", "Joe", "mark" },
            Classification = "PG",
            Genre = null,
            MovieId = 0,
            Rating = 5,
            ReleaseDate = 2004,
            Title = null
        };

        var rep = mc.Create(model);
    }

Which calls this class via the controller:

public int Create(Movie movie)
    {
        int num;
        if (MovieRepository.Movies == null)
        {
            throw new Exception("Movies datasource is not available");
        }
        lock (MovieRepository._dsMovies)
        {
            DataRow str = MovieRepository._dsMovies.Tables["Movie"].NewRow();
            int num1 = MovieRepository._pk + 1;
            MovieRepository._pk = num1;
            int num2 = num1;
            movie.MovieId = num2;
            str["Id"] = num2;
            if (string.IsNullOrEmpty(movie.Title))
            {
                throw new Exception("Movie Title is mandatory");
            }
            str["Title"] = movie.Title.Trim();
            if (!string.IsNullOrEmpty(movie.Genre))
            {
                str["Genre"] = movie.Genre.Trim();
            }
            if (!string.IsNullOrEmpty(movie.Classification))
            {
                str["Classification"] = movie.Classification.ToString();
            }
            str["Rating"] = movie.Rating;
            str["ReleaseDate"] = movie.ReleaseDate;
            MovieRepository._dsMovies.Tables["Movie"].Rows.Add(str);
            if ((movie.Cast == null ? 0 : (int)((int)movie.Cast.Length > 0)) != 0)
            {
                this.AddCast(movie);
            }
            MovieRepository._dsMovies.AcceptChanges();
            num = num2;
        }
        return num;
    }

As you can see it checks for the title

if (string.IsNullOrEmpty(movie.Title))
        {
            throw new Exception("Movie Title is mandatory");
        }

Can I assert that exception? because as it stands after it fails I click on the output to check the fail log and I see this :

Test Name: CreateMovie

Test Outcome: Failed

Result Message: Test method Project.Test.UnitTest1.CreateMovie did not throw an exception. An exception was expected by attribute Microsoft.VisualStudio.TestTools.UnitTesting.ExpectedExceptionAttribute defined on the test method.

Result StandardOutput:

System.Exception: Movie Title is mandatory

at Movies.MovieRepository.Create(Movie movie)

at Project.Web.Controllers.MoviesController.Create(Movie movie) in c:\Users\Name\Documents\Visual Studio 2013\Projects\Project.Web\Project.Web\Controllers\MoviesController.cs:line 113

According to the result message it says it didn't throw an exception, when I know it did / should

Noctis
  • 11,507
  • 3
  • 43
  • 82
Code Ratchet
  • 5,758
  • 18
  • 77
  • 141
  • Did you step through the code? What did the code actually do? Please provide [a good, _minimal_, _complete_ code example](http://stackoverflow.com/help/mcve) that reliably reproduces your problem. – Peter Duniho Jun 21 '15 at 01:19
  • @PeterDuniho yes I've stepped through the code when creating a new movie from the UI and it throws an exception "Movie title is mandatory" – Code Ratchet Jun 21 '15 at 01:20
  • 1
    I didn't ask whether you stepped through the code when calling from the UI. The relevant scenario is whether you stepped through the code during the unit test. Did you actually _debug the unit test_? If so, what did you find? – Peter Duniho Jun 21 '15 at 01:22
  • @PeterDuniho apologies, yes I have debugged it, and it does throw the exception Movie Title is mandatory, I have just wrapper a try catch statement around the unit test and again the exception is caught – Code Ratchet Jun 21 '15 at 01:37
  • Note that `ExpectedException` will happily report success if test fails for any other reasons (like errors in "arrange" part)... Consider other approaches shown in http://stackoverflow.com/questions/933613/how-do-i-use-assert-to-verify-that-an-exception-has-been-thrown to capture particular exception at particular time. – Alexei Levenkov Jun 21 '15 at 01:48

1 Answers1

0

You could wrap your unit test in a try catch, and put a debug point in the catch, so you can see it happening, and easily debug it:

[TestMethod]
[ExpectedException(typeof(Exception), "Movie Title is mandatory")]
public void Create()
{
    var mc = new MoviesController();

    var model = new Movie
    {
        Cast = new[] { "Scott", "Joe", "mark" },
        Classification = "PG",
        Genre = null,
        MovieId = 0,
        Rating = 5,
        ReleaseDate = 2004,
        Title = null
    };

    try
    {
        var rep = mc.Create(model);
        Assert.Fail("This shouldn't be shown, because the above should have thrown an exception ! !");
    }
    catch (Exception e)
    {
        Console.Out.WriteLine("AH ha! caught it ! :) : " + e);
        throw;
    }        
}

As an extra bonus, you can Assert.Fail so it won't get past it if it doesn't throw the exception.

As an even added bonus, you shouldn't be throwing an Exception but rather your own exception? maybe MovieException, so then you can catch specifically that exception.

Noctis
  • 11,507
  • 3
  • 43
  • 82
  • No worries, hope it helped. Test on brother (or sister...) , and keep warm, Melbourne must be freezing ATM ... – Noctis Jun 21 '15 at 02:06
  • Yes it's very cold at the moment ha ha, bring back the summer! quick question say I just wanted to assert a message for example "Hello World" when the test is run is that possible? if so how? because I can't seem to find any docs online – Code Ratchet Jun 21 '15 at 02:12
  • what do you mean ? on the exception?! or just on object, or a return value? – Noctis Jun 21 '15 at 02:57
  • No just in general, so I wanted to create a new unit test, and inside that unit test it would just assert "Hello world" when I run all test, it has no object or return value it just simply asserts "Hello World" and the test passes – Code Ratchet Jun 21 '15 at 02:58
  • assert is a class that then asserts something: is true, is false, is same, is not, etc ... asserting "hello world" doesn't make sense to me ... you could `Assert.IsTrue(true,"good")`, but again, it's rather futile, isn't it ? – Noctis Jun 21 '15 at 03:02
  • correct it is, but I was more curious if anything to see if it could be done, because your right it had no meaning what so ever. I haven't done much with unit test, as the companies I have worked at normally have them all in place with the odd exception etc. Thanks again – Code Ratchet Jun 21 '15 at 03:05
  • 1
    Then go and have a read : [unit test introduction](http://www.codeproject.com/Articles/784791/Introduction-to-Unit-Testing-with-MS-tests-NUnit-a). Wrote it as an intro, but you can probably pick something interesting and/or useful :) – Noctis Jun 21 '15 at 03:14