1

I have a controller that depends on a Session variable. In order to unit test this controller, I came up with the following solution. It works but I'm wondering if there is a better/cleaner way. Thanks

Controller

    public JsonResult UpdateStatus(ImageUpdateStatus imageUpdateStatus, SessionStateItemCollection sessionItems = null)
    {
        var data = new object();
        string status = null;

        ImageInfo imageInfo = new ImageInfo();
        IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
        imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);

        IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
        IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();

        if (imageUpdateStatus.Task == "prep")
        {
            List<UpdateReasonForm> updateReasonForms;

            if (sessionItems != null)
            {
                updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
            }
            else
            {
                updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
            }

            foreach (var item in updateReasonForms)
            {
                if (item.ImageId == imageInfo.ImageId)
                {
                    status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
                }
            }

            data = new
            {
                status
            };
        }

        if (imageUpdateStatus.Task == "boot")
        {
            status = svcDevice.Boot(imageInfo.ImageId);

            data = new
            {
                status
            };
        }

        return this.Json(data, JsonRequestBehavior.AllowGet);
    }

Unit Test

        [TestMethod()]
    public void UpdateStatusTest()
    {
        BuildController target = new BuildController(); // TODO: Initialize to an appropriate value
        ImageUpdateStatus imageUpdateStatus = new ImageUpdateStatus(); // TODO: Initialize to an appropriate value
        imageUpdateStatus.ImageId = 3;
        imageUpdateStatus.Task = "prep";
        UpdateReasonForm updateReasonForm = new UpdateReasonForm();
        updateReasonForm.ImageId = 3;
        updateReasonForm.NewVersion = "TestThis";

        List<UpdateReasonForm> updateReasonForms = new List<UpdateReasonForm>();
        updateReasonForms.Add(updateReasonForm);

        var sessionItems = new SessionStateItemCollection();
        sessionItems["UpdateReasonForms"] = updateReasonForms;

        JsonResult actual;
        actual = target.UpdateStatus(imageUpdateStatus, sessionItems);
    }
Kailash P
  • 428
  • 3
  • 17
bcahill
  • 9,709
  • 1
  • 17
  • 10

3 Answers3

3

Instead of passing in the session values as a parameter you can mock the session state like here:

How do you mock the session object collection using Moq

Community
  • 1
  • 1
Mathias F
  • 15,906
  • 22
  • 89
  • 159
1

You have a dependency on Session. You could move your code into a testable method where you inject the dependency at the method level. It looks like you are on this path I would just abstract the code into its own method allowing you to test the functionality regardless of the whether the data comes from session or not.

 public JsonResult UpdateStatusDependencyInjection(ImageUpdateStatus imageUpdateStatus, Dictionary<string, object> sessionValues)
        {
        var data = new object();
        string status = null;

        ImageInfo imageInfo = new ImageInfo();
        IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
        imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);

        IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
        IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();

        if (imageUpdateStatus.Task == "prep")
        {
            List<UpdateReasonForm> updateReasonForms;

            if (sessionItems != null)
            {
                updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
            }
            else
            {
                updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
            }

            foreach (var item in updateReasonForms)
            {
                if (item.ImageId == imageInfo.ImageId)
                {
                    status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
                }
            }

            data = new
            {
                status
            };
        }

        if (imageUpdateStatus.Task == "boot")
        {
            status = svcDevice.Boot(imageInfo.ImageId);

            data = new
            {
                status
            };
        }

        return this.Json(data, JsonRequestBehavior.AllowGet);
    }
BentOnCoding
  • 27,307
  • 14
  • 64
  • 92
0

http://codingsmith.co.za/a-better-way-of-working-with-httpcontext-session-in-mvc/

This is my implementation of an interface wrapper for Session. Its currently in production and works fine, its injected into my controllers, but I can use one of the other implementations manually when testing

spaceman
  • 1,628
  • 1
  • 16
  • 19