Generate unit tests for your code using Smart unit tests

Standard

Smart Unit Tests is a new feature in Visual Studio 2015, Smart Unit Tests helps developers to explore their .NET code to generate test data and a suite of unit tests. For every statement in the code, a test input is generated that will execute that statement. A case analysis is performed for every conditional branch in the code. When you run these smart unit tests, you can easily see which tests are failing and add any necessary code to fix them. You can select which of the generated tests to save into a test project to provide a regression suite. As you change your code, rerun Smart Unit Tests to keep the generated tests in sync with your code changes.

You can right click on the class file or method, and select Smart Unit Tests context menu option.

Smart Unit Tests - Context menu option

Smart Unit Tests – Context menu option

A parameterized unit test is generated for this method. The test data is created to exercise the code paths in the method. Smart Unit Tests runs your code many times with different inputs. Each run is represented in the table showing the input test data and the resulting output or exception. The dropdown list in the smart unit tests window will display all the public methods, for which test data is generated.

Generated Test Data and Test cases

Generated Test Data and Test cases

Developers can save the unit test generated, by clicking on the save button of Smart Unit Tests window.Smart unit tests also helps you to identify potential problems in your code as well.

You can find more information about smart unit tests in MSDN

Happy Unit Testing :)

Creating Unit Tests for ASP.NET MVC 6 Applications

Standard

This post is about unit testing ASP.NET MVC 6 applications. Unlike MS Test, this post is using XUnit Framework, which is the currently used unit testing framework for ASP.NET 5 applications.

Similar to TestMethod, XUnit uses Fact / Theory attributes. You can find more comparison details here.

Unit testing class libraries

Here is the unit tests for calculator class, with Add method.

public class CalculatorTests
{
	[Fact]
	public void AddTest()
	{
		var number1 = 10;
		var number2 = 20;
		var expected = 30;

		Calculator calculator = new Calculator();
		var result = calculator.Add(number1, number2);

		Assert.Equal(expected, result);
	}
	
	[Theory]
	[InlineData(10, 10,20)]
	[InlineData(20, 20,40)]
	public void AddTest(int number1, int number2, int expected)
	{
		Calculator calculator = new Calculator();
		var result = calculator.Add(number1, number2);
		
		Assert.Equal(expected, result);
	}
}

And here is source code

public class Calculator
{
	public int Add(int number1, int number2)
	{
		return number1 + number2;
	}
}

Similar to ASP.NET 5 applications, unit test project also requires a project.json file.

{
    "dependencies": {
        "xunit.runner.kre": "1.0.0-*"
    },
    "frameworks": {
        "aspnet50": { },
        "aspnetcore50": { }
    },
    "commands": {
        "test": "xunit.runner.kre"
    }
}

You need to execute the kpm restore command to download the XUnit runner, once it is finished, you can execute k test command to execute the tests. XUnit test runner will display result like this.

XUnit Test Results

XUnit Test Results

If you looked into the XUnit test results you can see something like Total :3, it because of the Theory and InlineData attributes, XUnit will treat the test method as a different one.

Unit testing MVC Controllers

Unlike class libraries, MVC controllers are little difficult to unit test. As controllers contains business logic and database interactions, you need to decouple it and inject it. This project is an ASP.NET MVC 6 project, code is generated using ASP.NET Scaffolding, it uses Entity Framework 7.0 and SQL Server localDb for database operations. In solution I wrote code to decouple the database interaction using repository pattern.

Here is the controller class.

public class EmployeeController : Controller
{
	private IEmployeeRepository _employeeRepository;
	public EmployeeController(IEmployeeRepository employeeRepository)
	{
		_employeeRepository = employeeRepository;
	}
}

I am using ASP.NET dependency injection framework for injecting the repository class to the controller. You can find more details about ASP.NET dependency injection here

public void Configure(IApplicationBuilder app)
{
    app.UseErrorPage();
    app.UseServices(services =>
    {
        services.AddMvc();
        services.AddScoped<IEmployeeRepository, EmployeeRepository>();
    });
 
    app.UseMvc();
}

And here is my index method, which returns employees from the database using repository.

// GET: Employee
public IActionResult Index()
{
	return View(_employeeRepository.FindAll().ToList());
}

And here is the unit test for the same. I am using Moq framework for mocking the

[Fact]
public void VerifyIndexDisplaysAllEmployees()
{
	_employeeRepository.Setup(x => x.FindAll()).Returns(new List<Employee>()
	{
		new Employee() { Id = 1, Name = "Employee 1" },
		new Employee() { Id = 2, Name = "Employee 2" },
		new Employee() { Id = 3, Name = "Employee 3" }
	});

	var indexResult = _employeeController.Index() as ViewResult;

	Assert.NotNull(indexResult);
	var employees = indexResult.ViewData.Model as List<Employee>;
	Assert.Equal(3, employees.Count);
	Assert.Equal(1, employees[0].Id);
	Assert.Equal("Employee 3", employees[2].Name);
}

As XUnit doesn’t have equivalents for Test Initialize / Class Initialize / Setup / Teardown, I have wrote the code to setup the controller and mocks in the test class constructor.

private EmployeeController _employeeController;
private Mock<IEmployeeRepository> _employeeRepository;
public EmployeeControllerTests()
{
	_employeeRepository = new Mock<IEmployeeRepository>();
	_employeeController = new EmployeeController(_employeeRepository.Object);
	var mockModelMetadataProvider = new Mock<IModelMetadataProvider>();
	var viewDataDictionary = new ViewDataDictionary<object>(mockModelMetadataProvider.Object);
	_employeeController.ViewData = viewDataDictionary;
}

As part of Index action, we are returning model object(Employee list), if we didn’t set ViewData property, tests will fail, with Null reference exception. This is because the controller class internally uses the ViewData property to return the Model to the view, while running controller from Unit test context, ASP.NET runtime won’t inject the required services to the view data property, so you need to set it manually.

Here is the Details action.

// GET: Employee/Details/5
public IActionResult Details(System.Int32? id)
{
	if (id == null)
	{
		return new HttpStatusCodeResult(404);
	}

	Employee employee = _employeeRepository.Get(id);
	if (employee == null)
	{
		return new HttpStatusCodeResult(404);
	}

	return View(employee);
}

And here is the unit tests for the same.

[Fact]
public void VerifyDetailsReturns404IfEmployeeIdIsNull()
{
	_employeeRepository
		.Setup(x => x.Get(It.IsAny<int?>())).Returns<Employee>(null);

	var httpStatusCodeResult 
		= _employeeController.Details(null) as HttpStatusCodeResult;

	Assert.NotNull(httpStatusCodeResult);
	Assert.Equal(404, httpStatusCodeResult.StatusCode);
}

[Fact]
public void VerifyDetailsReturns404IfEmployeeNotFound()
{
	_employeeRepository
		.Setup(x => x.Get(It.IsAny<int?>())).Returns<Employee>(null);

	var httpStatusCodeResult 
		= _employeeController.Details(1) as HttpStatusCodeResult;

	Assert.NotNull(httpStatusCodeResult);
	Assert.Equal(404, httpStatusCodeResult.StatusCode);
}

[Fact]
public void VerifyDetailsReturnsEmployee()
{
	_employeeRepository.Setup(x => x.Get(It.IsAny<int?>())).
		Returns((int id) => new Employee() { Id = id, Name = "Employee " + id });

	var viewResult = _employeeController.Details(1) as ViewResult;

	Assert.NotNull(viewResult);
	var employee = viewResult.ViewData.Model as Employee;
	Assert.NotNull(employee);
	Assert.Equal(1, employee.Id);
}

Most of the above tests are pretty straight forward, you can understand pretty easily. Here is the create action method.

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Employee employee)
{
	if (ModelState.IsValid)
	{
		_employeeRepository.Save(employee);
		return RedirectToAction("Index");
	}

	return View("Create", employee);
}

And unit tests for the Create method. One problem with the create method is that, it is using ModelState property of controller class to validate the model. As the model class is using Data Annotations API for validating the model, it is very difficult to mock. So we need to use the actual property to mock validation errors.

[Fact]
public void VerifyCreateEmployeeRedirectsToError()
{
	_employeeRepository.Setup(x => x.Save(It.IsAny<Employee>()));
	var employee = new Employee() { Id = 1 };
	//Mocking the _employeeController.ModelState.IsValid = false
	_employeeController.ModelState.AddModelError("Error", "Name is Required");

	var createResult = _employeeController.Create(employee) as ViewResult;

	Assert.NotNull(createResult);
	Assert.Equal("Create", createResult.ViewName);
}

[Fact]
public void VerifyCreateEmployeeInsertData()
{
	_employeeRepository.Setup(x => x.Save(It.IsAny<Employee>())).Verifiable();
	var employee = new Employee() { 
		Id = 1, 
		Name = "Employee", 
		Designation = "Designation", 
		JoiningDate = DateTime.Now };

	var createResult = _employeeController.Create(employee) as RedirectToActionResult;
	Assert.NotNull(createResult);
	Assert.Equal("Index", createResult.ActionName);
	_employeeRepository.Verify();
}

This code

_employeeController.ModelState.AddModelError("Error", "Name is Required");

is used to mock the model validation error. XUnit running on the tests

XUnit MVC Test Results

XUnit MVC Test Results

.

Here is my model class.

public class Employee
{
	public int Id { get; set; }
	[Required]
	public string Name { get; set; }
	[Required]
	public string Designation { get; set; }
	[Required]
	public DateTime JoiningDate { get; set; }
	public string Remarks { get; set; }
}

Repository interface

public interface IEmployeeRepository
{
	Employee Get(int? id);
	void Save(Employee employee);
	void Delete(Employee employee);
	void Update(Employee employee);
	IEnumerable<Employee> FindAll();
}

And the project.json file.

{
  "dependencies": {
    "Kestrel": "1.0.0-beta1",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",
    "Microsoft.AspNet.Hosting": "1.0.0-beta1",
    "Microsoft.AspNet.Mvc": "6.0.0-beta1",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1",
    "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-*",
    "EntityFramework.SqlServer": "7.0.0-*",
    "Microsoft.AspNet.StaticFiles": "1.0.0-*",
	"xunit.runner.kre": "1.0.0-*",
	"Moq":"1.0.0-*"
  },
  "commands": {
    "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5001",
    "gen": "Microsoft.Framework.CodeGeneration",
	"test": "xunit.runner.kre"
  },
  "frameworks": {
    "aspnet50": {}
  }
}

You can find the source code here

Happy Unit Testing :)

K-MUG User Group Meeting On 20th December – Kochi

Standard
K-MUG Logo

K-MUG Logo

Kerala Microsoft User Group (K-MUG) is conducting monthly UG meeting on 20th December 2014, Kochi

Venue:
Startup Village, Kinfra Hi-Tech Park, Kalamassery, Kochi, Kerala.

Agenda

  • 02:00 – 02:10 Community updates
  • 02:10 – 02:50 C# 6.0 – New Features by Anuraj P
  • 02:50 – 03:30 Object/Relational Impedance Mismatch by Aravindan M P
  • 03:30 – 03:40 Tea Break & Networking (10 min)
  • 03:40 – 04:20 Microsoft and Open Source by Praveen Nair
  • 04:20 – 05:00 Azure Service Bus by Shiju Varghese

You can find more details on K-MUG event page, you can register here.

Command line scaffolding for ASP.NET 5

Standard

Last K-MUG Session, there was a demo related to ASP.NET MVC scaffolding. This post is about scaffolding support in ASP.NET 5. This post uses K runtime for scaffolding, you can do it using Visual Studio 2015 Preview as well.

  • Modify project.json, add “Microsoft.Framework.CodeGenerators.Mvc”: “1.0.0-*” under dependencies.
  • Add “gen”: “Microsoft.Framework.CodeGeneration”, under commands
  • You are done with the configurations. Updated project.json file will look like this.
    {
      "dependencies": {
        "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",
        "Microsoft.AspNet.Hosting": "1.0.0-beta1",
        "Microsoft.AspNet.Mvc": "6.0.0-beta1",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1",
        "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*",
        "EntityFramework.SQLite": "7.0.0-*",
        "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",
        "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-*",
        "Microsoft.AspNet.StaticFiles": "1.0.0-*"
      },
      "commands": {
        "webListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5010",
        "gen": "Microsoft.Framework.CodeGeneration"
      },
      "frameworks": {
        "aspnet50": {},
        "aspnetcore50": {}
      }
    }
    
  • Execute KVM Upgarde command in command prompt, to upgarde your K Runtime.
  • Now execute KPM Restore command in command prompt. It will restore all the required nuget packages for scaffolding.
  • To scaffold the controllers and view, you need to execute the following command – “k gen controller -m TaskItem -dc TaskContext“, where TaskItem is the model class, and TaskContext is the DBContext. (As I am using SQLite, I have created DBContext class, if you are using SQL Server, you don’t require this, scaffolder will generate it for you.) Here is the TaskContext class.
    public class TaskContext : DbContext
    {
    	public DbSet<TaskItem> Tasks { get; set; }
    	protected override void OnConfiguring(DbContextOptions builder)
    	{
    		builder.UseSQLite("Filename=tasksDb.sqlite;");
    	}
    
    	protected override void OnModelCreating(ModelBuilder builder)
    	{
    		builder.Entity<TaskItem>().Key(t => t.Id);
    		base.OnModelCreating(builder);
    	}
    }
    
    

Here is the generated output.

COMMAND LINE SCAFFOLDING FOR ASP.NET 5

COMMAND LINE SCAFFOLDING FOR ASP.NET 5

Customizing scaffolding templates.

Similar to previous versions of MVC, you can customize the templates by modifying the templates. In old versions of MVC, you can find the templates under “C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates” folder, but in ASP.NET 5, NuGet packages are stored on a per-user basis by default. So you can the scaffolding under following location – C:\Users\\.kpm\packages\Microsoft.Framework.CodeGenerators.Mvc\1.0.0-beta1\Templates\, you can modify the contents of the files, and you can re-generate using -f (force) option.

k gen controller -f -m TaskItem -dc TaskContext

Happy Programming :)