1

How to pass a successfully created object from Create action with a RedirectToAction?

All looks good in the action, just can't reference it in the test.

  [Test]
    public void a_new_trick_should_be_saved_to_db_when_date_created_field_is_blank_and_set_to_now() {
        var controller = new TricksController();
        var formCollection = new FormCollection() {
                                                        { "Name", "test" },
                                                        { "Description", "test desc" },
                                                        { "Votes", "" },
                                                        { "VideoURL", "" },
                                                        { "DateCreated", ""}
                                                  };
        //on success result is always null
        var result = controller.Create(formCollection) as ViewResult;

        //**this will never work as result is null when success
        var newlyCreatedThing = result.TempData["newlyCreatedThing"];

        //on fail result holds the errors list
        string errorMessage = "";
        if (result != null)
            errorMessage = result.TempData["Error"].ToString();
        Assert.IsEmpty(errorMessage);
    }

and action method:

  [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "Administrator")]
    public ActionResult Create(FormCollection collection)
    {
        var itemToCreate = _tricksTable.CreateFrom(collection);
        try
        {
            //validation enforced on model (as an override on Massive)
            var expandoNewlyCreatedTrick = _tricksTable.Insert(itemToCreate);

            //pass back newly created trick so that tests can make sure data is right
            TempData["newlyCreatedThing"] = expandoNewlyCreatedTrick;
            return RedirectToAction("Index");
        }
        catch (Exception ex)
        {
            TempData["Error"] = "There was an error adding the trick: "+ ex.Message;
            return View(itemToCreate);
        }
    }
Dave Mateer
  • 6,588
  • 15
  • 76
  • 125
  • 1- Put a break point in the first line of Action and see in which line it breaks, then you can trace it and find why it returns Null to Test result. – Amir978 Oct 14 '11 at 03:36
  • 2- In Unit Testing you are not allowed to transact with DB, you have to fake Insert method and avoid writing to DB. A good example of how to fake the methods: http://nerddinnerbook.s3.amazonaws.com/Part12.htm – Amir978 Oct 14 '11 at 03:38
  • 1
    Thanks @Amir978 - am giving up on this for now. I suspect TempData isn't working as I'm not in HttpContext and therefore not in a session.. so can't access tempdata. Re unit testing - am experimenting with hitting the db in all my unit tests, and am pleasantly surprised as to how fast it is, and the simplicity of not having to mock/stub/fake. – Dave Mateer Oct 16 '11 at 23:32
  • I mean when you run a method which transact with DB, you're doing a change on DB, and this is absolutely wrong. Imagine a scenario that you have to add a user. If you add/delete a user in Unit test, you have to add/delete many users and your DB will be full of junk data very soon! – Amir978 Oct 17 '11 at 01:02
  • 1
    Thanks @Amir978 I understand what you are saying. This is another strategy I'm using... more Ruby on Rails esque from what I've heard. Every unit test in this project starts with a known instance of data (this is all against a dev version of the db) which is generated in the [SetUp] method. I'll be blogging about this all soon. Will put on a link when done. – Dave Mateer Oct 17 '11 at 01:56
  • @Amir978 - that's what your set up and tear down is for (clear out the database). Go check out Rob Connery's TekPub MVC 3 series. He's hitting the database just like the ruby guys do. It got my interest piqued so I gave it a shot too and I'm with Dave, it's very surprising how fast it runs. Even when clearing out the database on each test! It's rewritten the rules on unit testing for me and ensure's I know my code works all the way to the core of the application. By not hitting a database you're never going to know for sure if that stored procedure works as you expect! :) – lloydphillips Oct 17 '11 at 03:36
  • @Dave - just realised you are in NZ too! :) Just took a brief look at your code. Isn't TempData stored in Session, in which case would it not appear inside a Mocked Context? – lloydphillips Oct 17 '11 at 03:37
  • @lloydphillips - yes I've been going through Robs MVC3 series and have enjoyed it a lot. I'm demoing www.pubtricks.co.nz next week to the Chch .NET User Group, and will hopefully be up in Auckland doing a Massive esque talk at SQLSaturday. Source code will be on github within the week. Maybe drop me an email on davemateer@gmail.com - would be good to talk to someone else using Massive. – Dave Mateer Oct 17 '11 at 22:20

0 Answers0