Design a site like this with WordPress.com
Get started

Unit Test Progress

My second attempt at Unit Testing for my application. Was I successful?

My first attempt at unit testing didn’t go so good. Well, not at all. I wasn’t able to do a thing other than to create a new project to contain the unit testing. I had two great videos that I was following but when it came to mocking the data it fell apart. I couldn’t make heads or tails of how to mock because of the way I did the methods in the controllers. Out of frustration, I abandoned unit testing until fixed my fat controllers.

On my last blog, Fat Controllers: Going on a Diet, I talked about how I watched a course on what I consider best programming practices. One of the topics covered was the separation of business logic from the controller. Using that knowledge I reworked a controller dealing with several reports to a service model. With that service in place, I felt it was time for another crack at unit testing and MOQ.

My last attempt at unit testing dealt with the MOQ aspect of things. I couldn’t figure out how to hook a MOQ to my database connections. Now that I have an IReportProverder service setup, it was easier to follow the videos.

Speaking of videos, I have been watching two different videos on using MOQ in unit testing. One introduces Autofac in testing and the other doesn’t. I’m not entirely sure what Autofac does so I skip that part of the tutorial and jump to the other video to continue. Both have the same concept but just go about it differently.

The two videos that I recommend to watch are Mocking in C# Unit Tests – How To Test Data Access Code and More by Tim Corey and Unit Testing: MOQ Framework by the Microsoft Visual Studio YouTube channel. Both tutorials use xUnit as the testing framework. The Microsoft Visual Studio has four videos on unit testing that are fantastic.

For the unit test framework, I started with MSTEST but switched to xUnit simply because all the tutorials I’ve seen were using xUnit. I’m sure if you learn one, you can learn the other.

Since I’m using the .NET Framework I had to do some tweaks to xUnit to get it working. The xUnit documentation says that you have to use the .NET Core template when you create your test project but then make a change to the project file. It’s not a difficult change, just change the target framework from the current version to that of what you are using. In my case, it’s version 4.5.2.

FROM:
<TargetFramework>net5.0</TargetFramework>

TO:
<TargetFramework>net452</TargetFramework>

One last configuration I had to do was to set the project reference. Without that reference, it would have a build error. It was simple enough to do. Right-click on the project name and select Add, Project Reference, then check the main project you are working on. That’s it. I can now start creating unit tests.

using colttdb.Controllers;
using colttdb.Models;
using colttdb.Providers;
using Moq;
using System;
using System.Collections.Generic;
using Xunit;

namespace colttdb.Tests
{
    public class ReportsProvider
    {
        [Fact]
        public void GetAllCoursesbyTerm_validList()
        {
            // Arrange
            string Term = "FALL 2022";
            var mock = new Mock<IReportsProvider>();
            mock.Setup(x => x.GetAllCoursesbyTerm(Term)).Returns(GetSampleAllCourses());
            var controller = new ReportsController(mock.Object);
            var expected = GetSampleAllCourses();

            // Act
            var actual = controller.GetAllCoursesByTerm(Term);

            // Assert
            Assert.True(actual != null);
            Assert.Equal(expected.Count, actual.Count);
            for (int i = 0; i < expected.Count; i++)
            {
                Assert.Equal(expected[i].Term_Desc, actual[i].Term_Desc);
                Assert.Equal(expected[i].AboutProfessor, actual[i].AboutProfessor);
                Assert.Equal(expected[i].Department, actual[i].Department);
                Assert.Equal(expected[i].AccessibilityAlly, actual[i].AccessibilityAlly);
                Assert.Equal(expected[i].AccessibilityVideoCaptions, actual[i].AccessibilityVideoCaptions);
                Assert.Equal(expected[i].BasedOn, actual[i].BasedOn);
                Assert.Equal(expected[i].BlackBoardTemplate, actual[i].BlackBoardTemplate);
                Assert.Equal(expected[i].CourseCopiedById, actual[i].CourseCopiedById);
                Assert.Equal(expected[i].Class_CRN, actual[i].Class_CRN);
                Assert.Equal(expected[i].Camp_Code, actual[i].Camp_Code);
                Assert.Equal(expected[i].Citations, actual[i].Citations);
                Assert.Equal(expected[i].Class_Number, actual[i].Class_Number);
                Assert.Equal(expected[i].Class_Section, actual[i].Class_Section);
                Assert.Equal(expected[i].Class_Subject, actual[i].Class_Subject);
                Assert.Equal(expected[i].College, actual[i].College);
                Assert.Equal(expected[i].Contacted, actual[i].Contacted);
                Assert.Equal(expected[i].ContentStructure, actual[i].ContentStructure);
                Assert.Equal(expected[i].Deleted, actual[i].Deleted);
                Assert.Equal(expected[i].Faculty_Oid_Rgv, actual[i].Faculty_Oid_Rgv);
            }
        }

        private List<Course> GetSampleAllCourses()
        {
            List<Course> output = new List<Course>
            {
                new Course
                {
                    Id = 1,
                    Term_Desc = "FALL 2021",
                    Deleted = false,
                    InstructionalDesigner = "ray.garza@utrgv.edu",
                    CourseCopiedById =  "Yes",
                    Faculty_Oid_Rgv = "user1@utrgv.edu",
                    AboutProfessor = "Yes"
                },
                 new Course
                {
                    Id = 2,
                    Term_Desc = "FALL 2021",
                    Deleted = false,
                    InstructionalDesigner = "ray.garza@utrgv.edu",
                    CourseCopiedById =  "Yes",
                    Faculty_Oid_Rgv = "user1@utrgv.edu",
                    AboutProfessor = "Yes"
                },
                  new Course
                {
                    Id = 3,
                    Term_Desc = "FALL 2021",
                    Deleted = false,
                    InstructionalDesigner = "Marilu.Reyes@utrgv.edu",
                    CourseCopiedById =  "Yes",
                    Faculty_Oid_Rgv = "user1@utrgv.edu",
                    AboutProfessor = "Yes"
                },
                   new Course
                {
                    Id = 4,
                    Term_Desc = "FALL 2021",
                    Deleted = false,
                    InstructionalDesigner = "Marilu.Reyas@utrgv.edu",
                    CourseCopiedById =  "Yes",
                    Faculty_Oid_Rgv = "user1@utrgv.edu",
                    AboutProfessor = "Yes"
                },
                    new Course
                {
                    Id = 5,
                    Term_Desc = "FALL 2021",
                    Deleted = false,
                    InstructionalDesigner = "Christopher.Jazinski@utrgv.edu",
                    CourseCopiedById =  "Yes",
                    Faculty_Oid_Rgv = "user1@utrgv.edu",
                    AboutProfessor = "No"
                },
            };
            return output;
        }
    }
}

The above code is my unit test that checks a method that gets all courses with a given term. The Arrange is where I do all the setting up and assigning the mock data. Down at the bottom is a sample list of courses that I mocked to act as the database.

Next is the Act where I call the method in the controller which runs through the process of getting the data but not from the database but from the mock that I created (GetSampleAllCourses()).

Finally, the Assert section is where I do all the checking. In this case, I check to see if something was actually returned. If it is null, then something is wrong. Then I count the number of records retrieved against what is expected. Finally, I use a loop to run through all the records in the list and check each field is the same as expected.

How detailed the checks you perform is up to you as the developer. There may be requirements that you have to follow, or there might be time constraints that limit how much testing can be developed. As I continue to learn all about testing and I’m sure my thoughts on this will change.

One last topic I like to touch on is mocking. Personally, I love the concept of mocking data. I can set up various scenarios with known data with mocks and reuse it over and over without messing with an actual database. It’s a win-win situation.

Finally figuring out how to do unit testing has a very satisfying feel to it. Unit testing along with putting my fat controllers on a diet via services are new tools that I can put in my toolbelt and feel confident that I am becoming a better developer. Baby steps.

Advertisement