Learning the Basics of N-Unit Testing

By Nick Kwiecien | Software Engineer

Introduction to Unit Testing

Coming into this I knew next to nothing about Unit testing. The testing I had implemented in the past had always been scrutinized as the wrong way of testing and not really unit testing but more like integration testing. Unit testing for me has been a way to fix nuances in code. For me, I’ve always used the approach of coding first and testing after but I have heard of cases where testing first methodology has worked. For those of you that are new to unit testing, in general, you might be able to find a better understanding of what unit testing is by using some of the documentation that I’ve found.

Definition of Unit testing - [http://searchsoftwarequality.techtarget.com/definition/unit-testing] (http://searchsoftwarequality.techtarget.com/definition/unit-testing) \s\s N-Unit - [https://www.nunit.org/] https://www.nunit.org/ \s\s N-Unit Quickstart guide - [https://www.nunit.org/index.php?p=quickStart&r=2.6.3] https://www.nunit.org/index.php?p=quickStart&r=2.6.3

Application of N-Unit Testing

I was cruising along having installed the package and created my first test but I hit a bit of a roadblock when I tried to test an ActionResult that was using AutoMapper. Having searched the internet for answers I began to wonder if it’s best to test things using AutoMapper. One of the first things I found out about AutoMapper is that my project was currently using a very old version of it. So, that needed to change. Next, I found out that the way I was using AutoMapper had changed with the new version so I now had outdated code in the project that needed to be updated. This was when I first noticed that I was on the right track to getting something out of testing.

Suddenly, I started to notice that when I ran my tests that they were failing strangely on a dll issue. As it turns out I’m using Resharper 9 which is not compatible after N-Unit version 2.6.4. For this to work properly you have to use Resharper version 10. I opted to just use the 2.6.4 version of N-Unit as I don’t want to go through upgrading Resharper right now.

For my first few tests I picked simple actions such as the add action returning the correct add view. When I originally set up this code a few years ago, I opted not to include the view name when returning the view. I quickly learned that for testing purposes that this not really a great way to ensure that the right view is being shown and have now added the view name when returned in the ActionResult. When testing the delete action I could find a good example of how to properly test JsonResults by verifying every string in the Json. I found this a great way to ensure that you are getting all of the correct values back instead of just checking one value. You can find examples of the issues as well as resolutions I’ve found in the code below.

Code Examples

	[TestFixture]
    public class FireDrillUnitTests
    {
        [TestFixtureSetUp]
        public void Initialize()
        {
            Mapper.Initialize(c => c.AddProfile<MappingProfile>());
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        [Test]
        public void TestAddView()
        {
            var controller = new BobbleController();
            var result = controller.Add() as ViewResult;
            if (result != null)
            {
                Assert.AreEqual("Add", result.ViewName);
            }
        }

        [Test]
        public void TestAddAction()
        {
            var controller = new BobbleController();
            var bobble = BobbleAddBase();
            var result = controller.Add(bobble);

            if (result != null)
            {
                Assert.IsInstanceOf<RedirectToRouteResult>(result);
            }
        }

        [Test]
        public void TestEdit()
        {
            var controller = new BobbleController();
            var result = controller.Edit(5) as ViewResult;

            if (result != null)
            {
                Assert.AreEqual("Edit", result.ViewName);
            }
        }

        [Test]
        public void TestDelete()
        {
            var controller = new BobbleController();

            var results = controller.Delete(5) as JsonResult;
            List<string> actual = results.Data as List<string>;
           
            if (actual != null)
            {
                Assert.AreEqual(3, actual.Count);
                Assert.AreEqual("true", actual[0]);
                Assert.AreEqual(1, actual[1]);
                Assert.AreEqual("", actual[2]);
            }
        }

        private AddModel BobbleAddBase()
        {
            return Builder<AddModel>.CreateNew()
                .With(x => x.PlayerNumber = default(int))
                .And(x => x.PlayerName = GetRandom.String(20))
                .And(x => x.Team = GetRandom.String(20))
                .And(x => x.IsDeleted = false)
                .And(x => x.ImagePath = GetRandom.String(20))
                .And(x => x.Condition = GetRandom.String(20))
                .Build();
        }

    }
	

		[HttpGet, Route(Name = "Add")]
        public ActionResult Add()
        {
            var addModel = new AddModel();
            return View("Add", addModel);
        }

        [HttpPost]
        public ActionResult Add(AddModel addModel)
        {
            if (ModelState.IsValid)
            {
                var bobble = Mapper.Map<Bobblehead>(addModel);

                if (addModel.Image != null)
                {
                    addModel.Image.SaveAs(HttpContext.Server.MapPath("~/App_Data/Images/") + addModel.Image.FileName);
                    bobble.ImagePath = addModel.Image.FileName;
                }
                _bobbleheadService.Save(bobble);
                return RedirectToRoute("Index");
            }
            return View(addModel);
        }

        [HttpGet, Route(Name = "Edit")]
        public ActionResult Edit(int? id)
        {
            Bobblehead bobble = _bobbleheadService.GetByIdOrDefault(id);
            EditModel editModel = new EditModel();
            Mapper.Map(bobble, editModel);
            return View("Edit", editModel);
        }

        [HttpPost]
        public ActionResult Edit(EditModel editModel)
        {
            var bobble = _bobbleheadService.GetByIdOrDefault(editModel.Id);

            Mapper.Map(editModel, bobble);
            if (ModelState.IsValid)
            {
                if (bobble.ImagePath != null)
                {
                    bobble.ImagePath = editModel.Image.FileName;
                }

                if (editModel.Image != null)
                {
                    editModel.Image.SaveAs(HttpContext.Server.MapPath("~/App_Data/Images/") + 		editModel.Image.FileName);
                    bobble.ImagePath = editModel.Image.FileName;
                }
                _bobbleheadService.Save(bobble);
                return RedirectToAction("Index");
            }
            return View("Edit", editModel);
        }
        [HttpPost]
        public JsonResult Delete(int id)
        {

            try
            {
                Bobblehead bobble = _bobbleheadService.GetByIdOrDefault(id);
                _bobbleheadService.SoftDelete(bobble);

                var json = new { success = true, id = id, exception = "" };

                return Json(json);
            }
            catch (Exception)
            {
                return Json("Error");
            }

        }

Conclusion

For my first round of testing I tried to keep it as simple as possible. From my early research and development, I could find ways to make the code I’ve written better. I look forward to making further changes to this project in the future to better my unit testing skills. I have found that unit testing really is a great thing and I’ve heard other people say it before but I only believed it when I tried it for myself.

Written on July 11, 2017