Saturday, 27 December 2014 00:00

Unit testing c#

Unit testing c#

In my Unit Testing article I talked about Unit Testing, in this article I’m going to talk about bits and bobs of Unit Testing in C#Unit Testing .Net . In this article we use Visual Studio Unit Testing or precisely Microsoft.VisualStudio.TestTools. UnitTesting package. My concentration in this article is Entity Framework business related logic and MVC unit testing.

Cleaning up the Database after the unit test

When you unit test a code working with the Database you should put the unit test class in transaction. This way you avoid tampering the Database and probably the errors and exception which arises because you insert duplicate Data in Database. What we intend here in simple words is to revert any changes we make to the DB during testing. To accomplish this goal when you use Entity Framework for persistence logic we initiate a transaction in the initialization method and then dispose the TransactionScope object (to revert changes) in the “clean up” method. Codes to achieve this are as follow:

    [TestClass]

    public class TestClassName

    {

        TransactionScope _trans;

        [TestInitialize()]

        public void Initialize()

        {

            _trans = new TransactionScope();

    //Other codes to initialize Data

 }

//TestMethods

        [TestCleanup()]

        public void CleanUp()

        {

            _trans.Dispose();

        }

    }

 

There may be some cases where you need the inserted or modified Data to be available for the next unit test method in a Test Class. In this case above code snippet is not useful since after every method running the changes in the Database will be reverted. To keep the Data in the Database for the next method and cleaning up the Database after the last method run you can use this code:

 

    [TestClass]

    public class TestClassName

    {

        static TransactionScope _trans;

 

        [ClassInitialize()]

        public static void Initialize(TestContext context)

        {            _trans = new TransactionScope();

    //Other codes to initialize Data

 }

//TestMethods

        [ClassCleanup()]

        public static void CleanUp()

        {            _trans.Dispose();

              }

    }

Please pay attention to the differences between the above and previous codes. First of all the TransactionScope object, Initialize and CleanUp methods are static. Second the Initialize method has one argument. Third [ClassInitialize()] and [ClassCleanup()] attributes are different than [TestInitialize()] and [TestCleanup()] ones.

MVC controller unit testing

Unit tests you write should focus on just one section of the code so if the section you unit test depends on another section to work correctly you should resolve that dependency somehow and decouple your unit test. This way your unit test when fails shows you exactly where the problem exists. However if you do not decouple your unit test, the error may have been caused because of the dependency.

OK, enough talking! Let’s review an example to see what I meant.  In this example you want to add Banner Management capability to a website and you develop with ASP.NET MVC. According to the MVC architecture you get the input from the user in View, process it in Controller and finally save it in Model. In this case we want to unit test the controller. To test the controller you decouple the controller test from the view by passing the accurate Data to the controller. You should also decouple it from the Model using Moq and repository concept. First you should use repository instead of accessing DataContext directly. Second you should follow some abstraction concepts i.e. using Interface instead of the direct implementation of class. I don’t go to the details of repositories; you can read my repository article. A sample controller which is ready to be unit tested would be like this:

    public class BannerController : Controller

    {

        private IBannerRepository _aRepository;

 private ILocationRepository _bRepository;

        public BannerController()

        {

            this._aRepository = new GenericRepository<Banner>();

            this._bRepository = new GenericRepository<BannerLocation>();

 }

        public BannerController(IBannerRepository _injectedARepository, ILocationRepository _injectedBRepository)

        {

            this._aRepository = _injectedARepository;

            this._bRepository = _injectedBRepository;

         }

}

 

As you can see with the one parameter constructor we can easily pass the implementation of the IBannerRepository. One of your choices to decouple your controller unit test from Model is to implement IBannerRepository in a way which it just helps the unit test to be run as expected. This option is way too time-Consuming and it leads to tons of implementations just intended for testing. Another better choice is to use Moq package which it helps us to define the implementation of an Interface and use the Interface directly. An example to mock the IBannerRepository for the BannerController Create method in it's unit test is as follows:

    [TestClass()]

    public class BannerControllerTests

    {

        TransactionScope _trans;

        private Mock<IBannerRepository> mockIBannerRepositorys;

        private Mock<IGenericRepository<BannerLocation>> mockLocations;

        private BannerController controller;

        [TestInitialize()]

        public void Initialize()

        {

            _trans = new TransactionScope();

            var instanciatedBannerObjects = new Banner[]

            {

                new Banner {ID = 1, Title = "A1", BannerLocationID = 1, ImageFile = "Image1.jpg"},

                new Banner {ID = 2, Title = "A2,  BannerLocationID = 2},

                new Banner {ID = 3, Title = "A3", BannerLocationID = 3},

                new Banner {ID = 4, Title = "A4", BannerLocationID = 1}

            };

 

            var instanciatedLocationObjects = new BannerLocation[]

            {

                new BannerLocation {ID = 1, Caption = "L1"},

                new BannerLocation {ID = 2, Caption = "L2"},

                new BannerLocation {ID = 3, Caption = "L3"},

                new BannerLocation {ID = 4, Caption = "L4"},

            };

            mockIBannerRepositorys = new Mock<IBannerRepository>();

            mockIBannerRepositorys.Setup(m => m.GetAll()).Returns(instanciatedBannerObjects.AsQueryable());

 

            mockIBannerRepositorys.Setup(m => m.GetBanners(It.Is<int>(t => t == 1))).Returns(instanciatedBannerObjects.AsQueryable().Where(t => t.ID == 4));

            mockIBannerRepositorys.Setup(m => m.GetBanners(It.Is<int>(t => t == 4))).Returns(Enumerable.Empty<Banner>().AsQueryable());

 

            mockLocations = new Mock<IGenericRepository<BannerLocation>>();

            mockLocations.Setup(m => m.GetAll()).Returns(instanciatedLocationObjects.AsQueryable());

 

 

            controller = new BannerController(mockIBannerRepositorys.Object, mockLocations.Object);

        }

 

 

        [TestCleanup()]

        public void CleanUp()

        {

            _trans.Dispose();

        }

    }

 

What we have done here was mocking all the Repositories in order to avoid any errors which arise because of some errors in Repository Implementation and Database problems. This can be done by creating the object(IRepository instance) using Mock:

var mockIBannerRepositorys = new Mock<IBannerRepository>();

Mocking a method can be done using Setup method. We simply return a list when a “Select” query method is called. The rule of thumb for mocking methods is to return whatever you need to complete your test case.

MVC Controler Unit Testing test-case

For creating Banner the sudocode for my controller is like this:

  • Check the ModelState status
  • IF true then call custom Validation methods
  • IF no errors are reported Call repository Add method and save the Banner
  • IF no errors are reported Fill Success message
  • Pass Error Or Success Message to the View

As you can see Controller is actively communicate with the Model and View. The role of Controller here is to flow the Data between Models and then pass it to the View. This is exactly what we should Unit Test. Here in writing test case you don’t worry what happens if Validation method throw exception or what if Add method fails because you mock all of these functions and you receive what exactly your Test Case is based on. For example one of my test case for the BannerController is like this:

            #region Test case 1: Check what happend in case of ModelState errors 

            var modelRequiredTests = new Banner()

            {

                LocationId = 1,

                ImageFile = "this.png"

            };

            controller.ModelState.AddModelError("Title", "Required");

            var resultRequiredTests = controller.CreateBack(modelRequiredTests) as ViewResult;

            Assert.IsNotNull(resultRequiredTests);

            Assert.IsNotNull(resultRequiredTests.ViewBag.FinalStatus);

            Assert.IsFalse((resultRequiredTests.ViewBag.FinalStatus as ResultStatus).Success);

            Assert.AreEqual(ResultDisplayType.DontShow,

                (resultRequiredTests.ViewBag.FinalStatus as ResultStatus).DisplayStatus);

            //Add method should not be called, so we check it here

            try

            {

                mockAdverts.Verify(m => m.Add(It.IsAny<Banner>()));

                Assert.Fail("Add method is called!");

            }

            catch (Exception exception)

            {

                Assert.IsInstanceOfType(exception, typeof (MockException));

            }

 

 

            #endregion

 

What we have tested is the final Message passed to the View and the flow in Controller Create Post method. We have added a ModelError because we assume the title is not inputted in our test case and this is what happens automatically IF View does his part correctly. In this case the Add method of repository should not be called and we check that using Mock object Verify method. The message from our Controller to the view should be appropriate also; in this case “False” (because the operation is not succeeded) and no Message should be reported to the user (the ModelState Error will be outputted automatically). Please note that the FinalStatus variable is filled in Controller depending on the return values of Model functions.

MVC Model unit testing

Testing Model methods are easier since you’re dealing neither with controller nor with the View so your concentration is on the logic of the code. The main work to unit test Model is around repositories and the queries behind them. The key for a successful Repository unit testing is in initializing Data so it reflects precisely the input and the output of a method. After that the “Act” and “Assert” part of the TestMethod is pretty much easy. You just call the method you want to test with the initialized Data and check the result with what you expect to be returned. For an example you can see my Add Related Entity article.

Published in C#
Saturday, 27 December 2014 00:00

Unit testing

Unit Testing

Unit Testing has become an important part of software development no matter what language you’re developing with. Java Programmers use JUnit. PHP developers who use symfony are well familiar with the concept of unit testing and lime, although PHPUnit library is also available for PHP developers.  .Net developers have a lot of choices for unit testing; NUnit and MSTest are some packages from the long list. In this article I am going to talk about goals of Unit Testing and cases you should test with Unit Testing, if you want to learn Unit Testing in c# read this article.

Testing has been and will be a part of software development. Testing the final product should be only for the purpose of Integration Testing and other methods of automatic testing such as Unit testing and UI testing should be invoked during the development. During the development, development team should insure the accuracy of every single component and part i.e. a single function, a single package or library or a User Interface should behave correctly. After the development of each part, integration testing will be run to insure the accuracy of system when all components are working together.

In order to achieve accuracy for a single module when other parts are not ready and you cannot run the application you need Unit Testing. Consider Model, View, Controller (MVC) architecture and a team of two that are working concurrently on Model and View. Well in this case, the Model section developer is writing queries and business logic while the UI developer is working on GUI. None of them can test the application because yet no complete application is ready for testing but if they just write codes and do not test it, the time for the final debugging will be a lot more comparing to a case where these developers write Unit Tests and insure the accuracy of their developed parts. In addition to the concurrent development with a good precision Unit Testing reduces from testing time after some changes. Changing a query to satisfy another condition, removing an input from a UI or etc. can impose bugs on other developed parts of an application and if you have no Automatic Testing in place you should manually run all the tests you previously did whereas with Unit Testing in place you easily may detect bugs which are results of changes.

The concept behind Unit-Testing is easy to comprehend; see if a single section works as expected. For example you want to write a query to select last services, guests have used in a hotel. Well if one asks you what you expect in return of this query you probably know; you can manually select those services from a list of 10 records in an excel file. OK Unit Testing is based on such test case i.e. you provide those 10 records for the method (which is written to fetch required Data) and tell the Unit Testing method to inspect if the written method returns those Data we expect.
As a rule of thumb, Unit Testing states that you don’t need to test third party packages and libraries just focus on what you have added. This means if your work is completing another teammate’s you don’t need to worry about the accuracy what he or she has developed. This is a crucial rule for Unit Testing because we expect unit testing to clarify exactly which unit is defected! You MUST write Unit Tests as independent as possible but this should not mislead you! Some people think using third party packages or frameworks insure the accuracy of what they develop and they do not need to write Unit Test at all. This is what happened when I asked one of my developers for unit tests and in response he told me I am using “Entity Framework” and I am sure Microsoft has tested it! “Entity Framework” is working fine but what we write is not and we should write Unit Tests to insure the accuracy of our codes.

Sometimes figuring what part of the code needs Unit Testing and decoupling unit test may be tricky. I tried to provide samples and points about what to unit test when you develop with C# ASP.NET MVC and use Entity Framework and I hope by reading that article you get and overview of what to Unit-Test in an ASP.NET developed application.

Published in Testing
Advanced Programming Concepts
News Letter

Subscribe our Email News Letter to get Instant Update at anytime