NUnit Test MVC Controller

We want to test the controller in an MVC application. We want to pass values in and be able to catch the response.

The response from our controller will tell us if the test has passed or failed. If you build the application well then all these tests should pass once they get the right response.

Previously On Serversncode

All source code for the project can be found here

Getting started.

To Recap our project

  • NUnit_Demo.Web
  • Nunit_Demo.Data
  • Nunit_Demo.Tests
  • Nunit_Demo.Web is the MVC application.

NunitDemo.Data is a class library that get's called by the HomeController in the NunitDemo.Web application. This pretends to talk to a database for the purpose of these samples.

Nunit_Demo.Tests is where the tests take place and run from.

To test an MVC Controller we need to add MVC to our Test project. We can do this in NuGet

PM> Install-Package Microsoft.AspNet.Mvc

for more information

Now to our test setup.

We are going to test saving a user. In our Nunit_Demo.Data we add a new class called User

public class User
{
    public string Email_VC { get; set; }
    public string FirstName_VC { get; set; }
    public string LastName_VC { get; set; }
    public int Number_IN { get; set; }
}

Next we add a new class called UserQueries

    public int InsertUser(string sFirstName, string sLastName, string sEmail, int iNumber)
    {
        int iUserID = 0;



        // Create our user 
        User _user = new User
        {
            Email_VC = sEmail,
            FirstName_VC = sFirstName,
            LastName_VC = sLastName,
            Number_IN = iNumber
        };

        // Add code here to save user to the database.
        iUserID = 1;

        return iUserID;
    }

    public Boolean DeleteUser(int iUserId)
    {
        Boolean bSuccess = false;

        // Here we add code to delete the user from the database.
        bSuccess = true;

        return bSuccess;
    }

Our UserQueries has two methods. InsertUser and DeleteUser as before to keep things clean I've pretended to hit a database of some kind.

Now into our Nunit_Demo.Web Project we open the HomeController and add a method called SaveUser

    //Save User method to demonstrate Unit testing of parameters
    public ActionResult SaveUser(string firstname, string lastname, string email, int number)
    {
        UserQueries UQ = new UserQueries();

        int iUserId = 0;
        Boolean bValid = true;

        // Validate User Input
        // Do we have a first name
        bValid = (firstname == "" ? false : true);

        // Do we have a last name
        bValid = (lastname == "" ? false : true);

        // Do we have an email
        bValid = (email == "" ? false : true);




        // If Valid Save User
        if (bValid)
        {
            iUserId = UQ.InsertUser(firstname, lastname, email, number);
        }


        if (iUserId == 0)
        {
            return Redirect("/saveuser?message=MESSAGEHERE");
        }
        else
        {
            return Redirect("/UserAdded");
        }

This is a simple ActionResult method for MVC. It takes the parameters and then uses a redirect to pass you onto the next page or return you back to the save user page.

In this case if the parameters are missing it will set bValid to false and send you into a redirect to saveuser with a message.

Testing a controller

So back into our Nunit_Demo.Tests

We create a class UserTest

[TestFixture]
public class UserTest

Our first test is the easy one, Create a test user and get the UserID from the response of the controller.

    [Test]
    public void CreateUserTest()
    {
        string sFirstName = "James";
        string sLastName = "Test";
        string sEmail = "test@serversncode.com";
        int iNumber = 7;
        Boolean bTestSuccess = false;
        string sMessage = "";


        HomeController _homeController = new HomeController();

        ActionResult result = _homeController.SaveUser(sFirstName, sLastName, sEmail, iNumber);

        var actResult = (RedirectResult)result;
        int iUserID = 0;

        // User Added successfully
        if (actResult.Url.StartsWith("/UserAdded?id="))
        {
            // We remove the URL and pull the ID for the new user we just created
            string sURL = actResult.Url.Replace("/UserAdded?id=", "");

            iUserID = Convert.ToInt32(sURL);

            // If the user ID not 0
            if (iUserID != 0)
            {
                bTestSuccess = true;
                sMessage = "User Saved ok";
            }
            else
            {
                // If UserId is 0 something went wrong and the User didn't save ok, 
                // So the test fails.
                bTestSuccess = false;
                sMessage = "User Save failed";
            }
        }
        else
        {
            // If the result URL is Save user
            string sURL = actResult.Url.Replace("/saveuser?message=", "");



            // The test has passed if this code is hit.
            bTestSuccess = true;
            sMessage = "";
        }


        // Test fails if bTestSuccess is false;
        Assert.IsTrue(bTestSuccess, sMessage);

    }

I have a bit of code here so lets work trough it.

        string sFirstName = "James";
        string sLastName = "Test";
        string sEmail = "test@serversncode.com";
        int iNumber = 7;
        Boolean bTestSuccess = false;
        string sMessage = "";

We setup our parameters and values for the testing.

        HomeController _homeController = new HomeController();

        ActionResult result = _homeController.SaveUser(sFirstName, sLastName, sEmail, iNumber);

We then call our Home Controller.

NOTE: there are a number of ways to do this but I like this way, it's clean and easy to maintain over time.

        var actResult = (RedirectResult)result;
        int iUserID = 0;

Our SaveUser method responds with an ActionResult. We know for this that we are getting a RedirectResult as a response so we can cast that into our actResult.

        if (actResult.Url.StartsWith("/UserAdded?id="))

We then check our actResult.URL method if it starts with /UserAdded we know that the user was added successfully. Because that is the response we are expecting.

            string sURL = actResult.Url.Replace("/UserAdded?id=", "");

            iUserID = Convert.ToInt32(sURL);

Here I simply strip the url of the expected characters and leave myself with an int that I can easily convert.

            if (iUserID != 0)
            {
                bTestSuccess = true;
                sMessage = "User Saved ok";
            }
            else
            {
                // If UserId is 0 something went wrong and the User didn't save ok, 
                // So the test fails.
                bTestSuccess = false;
                sMessage = "User Save failed";
            }

We check to see is the userID 0 or not. If it is 0 we know this test has failed because this test should have saved a user to the system.

If iUseID is not 0 then we have a successful test.

        else
        {
            // If the result URL is Save user
            string sURL = actResult.Url.Replace("/saveuser?message=", "");



            // The test has passed if this code is hit.
            bTestSuccess = true;
            sMessage = "";
        }

Our SaveUser controller can send two redirect responses. One is the saved. and the user is a saveuser with a message.

If in this case our controller responds with /saveuser the test has succeeded, because if something has gone wrong and it hasn't allowed the user to move on. The system failed but sent the user back to the first screen.

NOTE: This isn't always the case and you might consider this a fail but that's open for you to decide.

        Assert.IsTrue(bTestSuccess, sMessage);

Our test will pass if the bTestSuccess flag is true. It's a simple yes / no test.

Ok so lets make the test do a bit more. Our controller validates the user input so it checks to see if we pass in the firstname, lastname or email.

We create a new test and set the firstname and lastname parameters to ""

        string sFirstName = "";
        string sLastName = "";
        string sEmail = "test@serversncode.com";
        int iNumber = 7;
        Boolean bTestSuccess = false;
        string sMessage = "";


        HomeController _homeController = new HomeController();

        ActionResult result = _homeController.SaveUser(sFirstName, sLastName, sEmail, iNumber);

        var actResult = (RedirectResult)result;
        int iUserID = 0;

The top part of this test is the same as our last test.

        // User Added successfully
        if (actResult.Url.StartsWith("/UserAdded?id="))
        {
            // With this test we are not expecting to be here. 
            // If we are then something went wrong in our validation.
            bTestSuccess = false;
            sMessage = "User Save failed";
        }

This is were it gets interesting. Because of our validation in the controller we should not get here. Our redirect should not send the user added. If it does the test has failed.

        else
        {
            // If the result URL is Save user
            sMessage = actResult.Url.Replace("/saveuser?message=", "");

            // The test has passed if this code is hit.
            bTestSuccess = true;
        }

We should come here with a message of some kind. The test has passed. Our controller validated the parameters found the missing values and sent it back.

About these tests

These tests are very simple and I think in most cases tests should be simple. Like anything in programming we can make things as complicated or as simple as we want. Really it depends if you want to punish yourself in 4 weeks time. If you don't then keep it simple.

I will be going deeper into the rabbit hole of making tests more complex but overall if I can I keep my tests clean and simple.

By doing that and sticking to it the tests are easy to maintain as the code base grows it can be maintained easier. There is less reason to remove tests or ignore them, which happens when tests are too complex or over the top.

We want to test the controller in an MVC application. We want to pass values in and be able to catch the response. The response from our controller will tell us if the test has passed or failed. If you build the application well then all these tests should pass…

Read More

Building Real NUnit Tests

Using NUnit tests is about testing different aspects of your application. So that as you make changes and add features you don't break anything. But it can be hard to get started with unit testing. Sometimes we are in too much of a rush to add testing to our applications if we don't take the time to add it in at the start but it doesn't have to be.

In this post I'm going to cover building some small real world tests to test parts of an application. It only takes 5 / 10 mins to do this.

Cloudstatus.eu is a web application I created for monitoring Cloud infrastructure we use to build services. It monitors Azure, AWS, Google Cloud, Github and more and sends alerts to your inbox or slack and more places.

To keep everything clean I've created a sample application that is a smaller version of Cloudstatus.eu and added some tests to it.

You can get the source here

If you are looking for how to add NUnit check out my blog post Your first NUnit Test

The Setup
  • NUnit_Demo.Web
  • Nunit_Demo.Data
  • Nunit_Demo.Tests

Nunit_Demo.Web is the MVC application.

NunitDemo.Data is a class library that get's called by the HomeController in the NunitDemo.Web application. This returns a list of providers.

Nunit_Demo.Tests is where the tests take place and run from.

In Nunit_Demo.Data we have a class ProviderQueries

    public List<Provider> GetProviders()
    {
        List<Provider> _records = new List<Provider>();

        _records.Add(AddProvider(1, "Azure", "Windows Azure", "All Ok", "Running Fine"));
        _records.Add(AddProvider(2, "AWS", "Amazon Web Services", "All Ok", "Running Fine"));


        return _records;
    }


    // This method will throw an expection to see the test failing.
    public List<Provider> GetProvidersNoDatabase()
    {
        List<Provider> _records = new List<Provider>();


        throw  new Exception("database missing");

        return _records;
    }

    public Provider AddProvider(int Id, string ProviderCode, string ProviderName, string Title, string Status)
    {
        Provider _record = new Provider
        {
            Id = Id,
            Provider_Code_CH = ProviderCode,
            Provider_Name_VC = ProviderName,
            Current_Title_VC = Title,
            Current_Status_VC = Status,
            Updated_DT = DateTime.Now,
            Display_Date = DateTime.Now.ToString(DateFormat),
            Preview_BT = false
        };

        return _record;
    }
}

I won't cover this in detail but we have a method GetProviders which will add some providers and return the list.

We also have a method called GetProvidersNoDatabase that will throw an Exception.

If you read my last post you'll know I like to watch tests break first just for fun.

The Tests

Ok lets create some tests. I did promise these are quick short tests you can add to any application.

In Nunit_Demo.Tests

Add the nuget packages for Nunit and Nunit test adapter.

We create a class "ProviderTests"

[TestFixture]
class ProviderTest

We add [TestFixture] and create our first method as below.

    [Test]
    public void LoadProviders()
    {
        List<Provider> _providers = new List<Provider>();

        Boolean bResult = true;
        string sStatusMessage = "";
        ProviderQueries PQ = new ProviderQueries();

        _providers = PQ.GetProviders();

        if (_providers.Count != 0)
        {
            bResult = true;
            sStatusMessage = "Yes has providers";
        }
        else
        {
            bResult = false;
            sStatusMessage = "No Providers";
        }

        Assert.IsTrue(bResult, sStatusMessage);
    }

This test calls the ProviderQueries class in the Nunit_Demo.Data class library.

_providers = PQ.GetProviders() will call the method and load the providers list.

if (_providers.Count != 0)

We then check the count for the list. If there are 0 records we know the test failed. This application should always have something.

Assert.IsTrue(bResult, sStatusMessage);

Assert is the basic Pass / fail for nunit tests. bResult is set to true or false depending on the number of records we have.

That's it, in under 20 lines of code we have a testr that will check if our application gets the providers back and we can move on.

Another way to do it

    [Test]
    public void LoadProviderNoDatabases()
    {
        List<Provider> _providers = new List<Provider>();

        ProviderQueries PQ = new ProviderQueries();

        _providers = PQ.GetProvidersNoDatabase();

        if (_providers.Count != 0)
        {
            Boolean bResult = true;

            Assert.IsTrue(bResult, "Providers loaded");
        }
        else
        {
            Assert.IsFalse(false, "No Providers loaded");
        }
    }

ProviderQueries also has a method that will always fail. So we have added that in here as a test.

Open test Explorer and run all we have 3 tests on our sample application our first test from the last post on getting started.

Test_explorer

As you can see 2 tests passed.

  • FirstTests
  • LoadProviders

  • LoadProvidersNoDatabases failed and as you can see in the Message the text from the exception we threw is loaded there.

These are simple and straight forward tests that take very little time to add to your application. Next we will start getting deeper and testing the user flow so what happens when someone signs up.

Using NUnit tests is about testing different aspects of your application. So that as you make changes and add features you don't break anything. But it can be hard to get started with unit testing. Sometimes we are in too much of a rush to add testing to our applications…

Read More

Your First NUnit Test

Nunit is a unit testing framework for .NET, it was ported from a Java called JUnit.

More About NUnit here. My earlier post about Testing and Unit testing About Unit Testing

Getting Started with NUnit

It's easy to add Nunit, just Create a new Class Library on your project.

Add NUnit_Demo.Tests

Then run Package installer and install the nuget package to the new class library

PM > Install-Package NUnit

Nuget here

Then in your new Class Library create a new Class - DemoTests, our first test will look like this.

[TestFixture]
class DemoTest
{

    [Test]
    public void FirstTest()
    {

        Assert.IsTrue(true, "Hello Test World!");
    }
}

[TestFixture]

Is added to the class, this will tell the test running that this class is for tests. But it has alot more power we'll get into that later in other posts.

Our First test method is simple.

[Test]

Tells the test running that this is a test.

Assert.IsTrue(true, "Hello Test World!");

Assert.IsTrue is how we tell the test has passed, failed or something else has happened.

Running the Test

But enough it's time to run the test. First thing, Add a reference to your Tests Libarary and reference the main project.

Then on the test page in Visual Studio 2017 you have an icon, on the right margin. When you mouse over it, it says "NUnit Test (click to run)"

NUnit Test

Click it! Go on Click it,

Run NUnit Test

And then hit run!

If you clicked it you have now run your first test congratulations.

I didn't have the NUnit Test Adapater installed at the time of running this test. I didn't need it, Visual Studio knows enough about the tests to be able to run it.

NUnit3 Test Adapter

Go ahead and install it and do the whole restart of Visual Studio.

Once your back in go to "Test - Windows - Test Explorer"

Test Explorer

This will open the Test Explorer window in Visual Studio and our "FirstTest" should be listed there. (If it isn't build the project, I find sometimes I have to run the web app in some cases to get VS to pick up my tests first)

Your First NUnit Test

You know what to do. Click run and lets watch what happens.

The test runs and passes because we told it to and we also see how long it took and we've green everywhere.

Passed Tests

I don't know about you but sometimes I don't trust a test has worked until I can watch it fail so lets make it fail.

This is easy to do, in the First test change the Assert.IsTrue line.

Assert.IsTrue(false, "Test has Failed!");

We've changed it to be false and also changed the note that will be output.

So when we run this test now it will fail.

First Test Failed

As you can see our first test has failed. We see the message we have loaded in as well in the output so we know why it failed.

Next time on Serversncode

As you can see it is really easy to create a NUnit test in Visual Studio 2017 but this is a very simple set of tests. Next Time around we'll start building some more detail tests. Getting into testing our Database connection and how do we test user signups.

I'll also go into how to wire into Visual Team Services and the full CI / CD and how to get these Unit tests to be a part of that process.

Next Part Real Nunit Tests

Nunit is a unit testing framework for .NET, it was ported from a Java called JUnit. More About NUnit here. My earlier post about Testing and Unit testing About Unit Testing Getting Started with NUnit It's easy to add Nunit, just Create a new Class Library on your project. Then…

Read More

About Unit Testing

As we move more and more into using continuous delivery we need to start getting better at building tests. Test Driven Development (TDD) was a trend and for a long time was the new hot, it's now been replaced by DevOps as the new trend but TDD is now more important then ever before and is a massive requirement to having a good DevOps practice.

I have a number of projects some of which I am the solo developer and I don't have a QA team to dump a load of work on so having good repeatable tests is important. It's also important to wire these tests into a CI / CD pipeline and I'm going to share how I do it, also I'm going to explore other tools and look into what I find and how can we use it. As a Solo Developer and as a team.

Test Driven Development

At it's very core TDD was all about building your test cases before or even as you develop but if you did it after no one would know unless you tell them.

As a developer it was a tool in our tool belt that allowed us to build software that we would know would just work. It makes it easy to expand and take change requests and build onto the base of the software because we can run these tests that would tell us when we break something and we always do.

About unit testing

Unit Testing is the basic part of testing. I found this definition online

Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation. Unit testing can be done manually but is often automated.

Source searchsoftwarequality.techtarget.com

It sums it up right. Unit testing is taking your application and testing different parts of it to make sure they work. Then joining all the parts to the flow of your application and testing that.

We've all been there, one part of our application fails and we spend hours debugging the whole application only to not find it.

Unit testing helps in this it gives us the ability to test the components individually and then as a whole application and it's all AUTOMATED!

Unit Testing Frameworks

The cool part is these frameworks are free - at least I've yet to find a unit testing framework that is priced.

.NET Frameworks

For .net I've found 3.

I mostly use Nunit when I am working in .NET it's quick and easy to build tests and I've been using it for years.

At the time of writing I haven't really started using XUnit but I plan on changing that I hear alot of good things about it.

Javascript

As with anything Javascript there are a few, but these 3 stand out as ones I want to try.

I'll admit at time of writing this, I've tried these with mixed results but I'm going to get down to them and do some more of a side by side with them for a later project. Karma and Protractor come from the Angular Team so might be something worth looking into more.

Ruby On Rails

Ruby on Rails is setup for testing, a bit like .NET has a built in testing.

Python

I don't do alot of python work but it has unit testing.

So Go Test!

As we move more and more into using continuous delivery we need to start getting better at building tests. Test Driven Development (TDD) was a trend and for a long time was the new hot, it's now been replaced by DevOps as the new trend but TDD is now more…

Read More

Development Machine

Developer Desktop Build

Having a good fast and powerful machine is important to every developer and if like me you enjoy building your own Computers then it's fun as well as important.

The advantage of building a machine is that I can upgrade parts as I go along. I've been building my own machines for over 10 years now. I've done the water cooling, air cooling, and I've even thought of building a computer in a fridge at one stage.

At the moment it is air cooled. I have a Termal take Armour case. It's an old case a solid heavy big tower, At this stage it's housed 4 different generations of Computers. This is the latest but by no means the last.

Intel Core i7 - 3930 K Processor - 3.2 GHz, 12 MB LGA-1155 3.2 GHz 6-core
I've had this CPU for a while now and it's a great CPU. Everything I have thrown at it. It's solid and powerful. One thing after having the Hex Core CPU for a while I don't think I'll go back to an quad core.
£159.99
MSI GeForce GTX 1070 ARMOR 8G OC. 1920 Cuda Core PCIE 3.0 8 GB GDDR5 256-Bit Graphics Card
For a while I ran with a 560Ti Graphics card. I waited until the new generation of cards where released. From a price point the 1080 just didn't make sense but the 1070 is a nice middle ground both on cost and performance is still really strong.
£382.61
G-Skill RipjawsZ F3-12800CL10Q-32GBZL 32 GB (8 GB x 4) DDR3 1600 MHz Unbuffered Non-ECC Memory Module with Heat Spreader
I have two sets of 32 GB of Ram and it is a must at this stage. 64 GB of ram just makes everything go so fast and there is plenty of ram for Chrome.
£240.49
Asus P9X79 Motherboard Socket 2011, Intel X79, DDR3, ATX, PCI Express 3.0
My current Motherboard. Has enough USB3.0 ports, plus SATA, no IDE port though which is fine I haven't needed or had a DVD drive for a while now.
£218.99
Samsung 850 EVO 500 GB 2.5 inch Solid State Drive
My Primary Hard drive. This is the only SSD drive in the machine at the moment.
£148.17
WD Blue 3TB Desktop Hard Disk Drive
The other harddrives I have in my machine are older Hard drives I've had for a while. This is my main Games harddrive.
£87.40
Akasa AK-CC4007EP01 Nero 3 CPU Cooler
The CPU doesn't ship with a stock cooler.
£32.34
iiyama X2783HSU-B1 27-Inch
My Main Monitor is a 27 inch, I was suprised how good the iiyama monitors are, but this is a really good monitor. Currently I am running 3 Monitors this 27 inch, plus 2 Samsung 22 Inch monitors.
£168.52
  • All prices are from Feb 2017 and Amazon UK
Upgrades

So far the machine is really good and solid but the next step is to upgrade.

Currently I have 5 Harddrives, 2 are SSD, one Evo and a Crucial SSD, I run my OS off the EVO and the Crucial runs my projects and databases.

The other harddrives are older and have been with me for a few years and different builds. I plan to replace them all with SSD harddrives.

I'm also looking at Icy Dock MB996SP-6SB 6-in-1 SATA Hot Swap Backplane Cage for RAID to hold the SSD's and drop the older harddrives.

My plan by upgrading the Hard drives these will come with me when I finally go for the next Mobo, CPU and RAM upgrade.

Developer Desktop Build Having a good fast and powerful machine is important to every developer and if like me you enjoy building your own Computers then it's fun as well as important. The advantage of building a machine is that I can upgrade parts as I go along. I've been…

Read More