Tuesday, 31 December 2013

Triggering Events in Angular JS Directive Tests

The best place to perform DOM manipulations in an Angular JS application is in a directive. Sometimes we handle events on the elements wrapped inside the directive to perform required action. The jQlite implementation in Angular JS provides enough APIs to handle these events in the body of the directives. We can use jQuery as well, if API exposed by jQlite is not enough.

One of the primary design goals of Angular JS is testability. Directives are testable too. Since we work directly on DOM with directives, testing becomes a bit tricky. One of such trickier part to test is event. Say, we have a directive that handles blur event on a text box:

app.directive('textBoxBlur', function($window){
  return{
    require:'ngModel',
    link: function(scope, element, attrs, ngModel){
      element.bind('blur', function(e){
        $window.alert("value entered: " + element.val());
      });
    }
  }
});

To call the DOM events manually, jQlite provides a handy method triggerHandler. It is similar to jQuery’s triggerHandler method. It can be fired using jQlite object of any element. Following statement shows this:
elem.triggerHandler('blur');

Since we have to do it repeatedly in tests, it is better to wrap it inside a reusable function as shown below:
changeInputValue = function (elem, value) {
    elem.val(value);
    elem.triggerHandler('blur');
};

Now the above function can be called from any test case to test behaviour of the blur event.
it('Should call alert on losing focus', function(){
  changeInputValue(form.find('input'), "Ravi");
  expect(windowMock.alert).toHaveBeenCalled();
});

Complete sample is available on plnkr: http://plnkr.co/edit/InkyGdIhZiwfe0NC4hyu?p=preview

Happy coding!

Monday, 30 December 2013

Self-Hosting ASP.NET SignalR Using Katana

With the recent release of ASP.NET, Microsoft added a new component, Katana. It is an implementation of OWIN (Open Web Interfaces for .NET) that provides a light weight alternative to create a .NET server quickly without needing any of the ASP.NET components or IIS. The server can be composed anywhere, even on a simple Console based application. For more information on Katana, read the excellent introductory article by Howard Dierking.

The project templates of ASP.NET that come with Visual Studio 2013 have some pieces of Katana also installed, as we saw some of them in my post on Identity system. It is used there to make the identity system available for across all flavours of ASP.NET.

Katana made the process of self-hosting ASP.NET Web API and SignalR very easier with its simple interface. Any Katana based application needs a startup class to kick the things off. We can perform any global configuration in this class. It includes hub route mapping in SignalR or API controller routing in Web API.

Let’s build a simple console-hosted SignalR application using Katana. Create a console application using Visual Studio 2013 and install the following NuGet package on this project:


Install-Package Microsoft.AspNet.SignalR.SelfHost


This package installs all the dependencies required to write and publish a SignalR application on a non-web based environment. Add a new class to the project; name it Startup and add the following code to it:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
}

The configuration method is used comparable to Application_Start event in Global.asax, it gets called at the beginning of the application. As we see, SignalR routes are mapped in the configuration method. We need to start the server in the Main method of the Program class. Add following code to the Main method:
static void Main(string[] args)
{
    string uri = "http://localhost:8080/";

    using (WebApp.Start<Startup>(uri))
    {
        Console.WriteLine("SignalR server started, start sending requests");
        Console.ReadKey();
        Console.WriteLine("Server stopped!");
    }
}

As there is no web server to host our application, we need to specify a port number where the server has to keep running. The generic static method WebApp.Start is called to start the server; it calls the Configuration method defined above. The server would stop once the console application stops running.

Let’s create a boring hello-world kind of hub. Following is a hub that takes name of a person and returns a greeting message with current time stamp:

public class HelloWorldHub : Hub
{
    public void Greet(string name) 
    {
        Console.WriteLine("Got a request from: {0}", name);
        string message= string.Format("Hello, {0}. Greeted at: {1}",name,DateTime.Now.ToString());
        Clients.All.acceptGreeting(message);
    }
}

Run the console application, you should be able to see the following message:

Let’s quickly create a console client to test if the server is able to push messages to the client. Create another console application and add the following NuGet package to it:


Install-Package Microsoft.AspNet.SignalR.Client


Add following code to the Main method:

static void Main(string[] args)
{
    var hubConnection = new HubConnection("http://localhost:8080/");
    var hubProxy = hubConnection.CreateHubProxy("HelloWorldHub");
    hubProxy.On<string>("acceptGreeting", message => {
        Console.WriteLine("Received from server: " + message);
        Console.WriteLine("\n\nPress any key to exit.");
    });

    Console.WriteLine("Establishing connection...");
    hubConnection.Start().Wait();
    Console.WriteLine("Sending request to hub...");
    hubProxy.Invoke("Greet", "Ravi").Wait();

    Console.ReadLine();
    hubConnection.Stop();
}

Run the client application, you should be able to see the following output:



Happy coding!

Sunday, 22 December 2013

Mocking promises in Angular JS Controller Tests

In a typical Angular JS application, we wrap the calls to backend services in a custom Angular JS service and return a promise from the method in the service to the calling component. For instance, say the calling component is a controller. While testing the controller, we create a mocked service instance with methods replaced by spies. As the original method in the service returns a promise containing the result from executing the backend API, the spy should return a mocked promise with a dummy result.

A few months back, when I was learning Angular and blogging my learning, I did blog posts on unit testing controllers using Jasmine and also on unit testing controllers using QUnit. Back then, I used to use spyOn().andCallThrough() on all methods in the service and used $httpBackend to avoid calling the backend APIs from the service. With time, I understood that this approach is not good as the controller still depends on the logic written inside the service. In this post, we will see how to return mock promises from the spies to isolate controller from the service.

Following are the service and the controller we will be using in this post:

var app = angular.module("myApp", []);
app.factory('dataSvc', function($http, $q){
    var basePath="api/books";
    getAllBooks = function(){
        var deferred = $q.defer();
 $http.get(basePath).success(function(data){
            deferred.resolve(data);
        }).error(function(err){
          deferred.reject("service failed!");
        });
        return deferred.promise;
     };
  
     return{
         getAllBooks:getAllBooks
     };
});

app.controller('HomeController', function($scope, $window, dataSvc){
   function initialize(){
       dataSvc.getAllBooks().then(function(data){
           $scope.books = data;
       }, function(msg){
          $window.alert(msg);
       });
   }

  initialize();
});

Let’s create a spy for the service. This is a bit tricky, as we need to force the promise to pass or fail based on a condition. At the same time, it is simple as $q provides the ready methods when and reject to make our job easier. Following is the spy for getAllBooks method:
var succeedPromise;
spyOn(booksDataSvc, "getAllBooks")
    .andCallFake(function(){
        if (succeedPromise) {
            return $q.when(booksData);
        }
        else{
            return $q.reject("Something went wrong");
        }
    });

The fake implementation of getAllBooks passes if value of the field succeedPromise is set to true, otherwise it fails. We need to manipulate this field in the test cases.

In the test cases, we need to call scope.$digest before checking the expectations, as the promise is triggered from a spy method, which is in non-angular world.

Following test case checks if the books object is set to some value when the promise passes.

it('Should call getAllBooks on creating controller', function(){
    succeedPromise = true;
    createController();
    homeCtrlScope.$digest();
    expect(booksDataSvc.getAllBooks).toHaveBeenCalled();
    expect(homeCtrlScope.books.length).not.toBe(0);
  });

The promise can be forced to fail by just setting succeedPromise to false in the test case. Following test case demonstrates it:
it('Should alert a message when service fails', function(){
    succeedPromise = false;
    createController();
    homeCtrlScope.$digest();
    expect(booksDataSvc.getAllBooks).toHaveBeenCalled();
    expect(windowMock.msg).not.toBe("");
  });

The complete sample is available on plnkr: http://plnkr.co/edit/xD9IPb6TRduAUwRGbIIG

Happy coding!

Wednesday, 18 December 2013

Unit Testing Asynchronous Web API Action Methods Using MS Test

Since Entity Framework now has a very nice support of performing all its actions asynchronously, the methods in the repositories in our projects will turn into asynchronous methods soon and so will be the code depending on it. Tom Fitzmacken did a nice job by putting together a tutorial on unit testing Web API 2 Controllers on official ASP.NET site. The tutorial discusses on testing synchronous action methods. The same techniques can be applied to test asynchronous action actions as well. In this post, we will see how easy it is to test asynchronous Web API action methods using MS Test.

I created a simple repository interface with just one method in it. The implementation class uses Entity Framework to get a list of contacts from the database.

public interface IRepository
{
    Task<IEnumerable<Contact>> GetAllContactsAsync();
}

public class Repository : IRepository
{
    ContactsContext context = new ContactsContext();

    public async Task<IEnumerable<Contact>> GetAllContactsAsync()
    {
        return await context.Contacts.ToArrayAsync();
    }
}

Following is the ASP.NET Web API controller that uses the above repository:
public class ContactsController : ApiController
{
    IRepository repository;

    public ContactsController() : this(new Repository())
    { }

    public ContactsController(IRepository _repository)
    {
        repository = _repository;
    }

    [Route("api/contacts/plain")]
    public async Task<IEnumerable<Contact>> GetContactsListAsync()
    {
        IEnumerable<Contact> contacts;
         try
         {
            contacts = await repository.GetAllContactsAsync();
         }
         catch (Exception)
         {
             throw;
         }
           
         return contacts;
    }

    [Route("api/contacts/httpresult")]
    public async Task<IHttpActionResult> GetContactsHttpActionResultAsync()
    {
        IEnumerable<Contact> contacts;

        try
        {
            contacts = await repository.GetAllContactsAsync();
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
        
        return Ok(contacts);
    }
}

As we see, the controller has two action methods performing the same task, but  the way they return the results is different. Since both of the action methods respond to HTTP GET method, I used attribute routing to distinguish them. I used poor man’s dependency injection to instantiate the repository; it can be easily replaced using an IoC container.

Before writing unit tests for the above action methods, we need to create a mock repository.

public class MockRepository:IRepository
{
    List<Contact> contacts;

    public bool FailGet { get; set; }

    public MockRepository()
    {
        contacts = new List<Contact>() {
            new Contact(){Id=1, Title="Title1", PhoneNumber="1992637281", CustomerId=1},
            new Contact(){Id=2, Title="Title2", PhoneNumber="9172735171", SupplierId=2},
            new Contact(){Id=3, Title="Title3", PhoneNumber="8361910353", CustomerId=2},
            new Contact(){Id=4, Title="Title4", PhoneNumber="7801274518", SupplierId=3}
        };
    }

    public async Task<IEnumerable<Contact>> GetAllContactsAsync()
    {
        if (FailGet)
        {
            throw new InvalidOperationException();
        }
        await Task.Delay(1000);
        return contacts;
    }
}

The property FailGet in the above class is used to force the mock to throw an exception. This is done just to cover more test cases.

In the test class, we need a TestInitialize method to arrange the objects needed for unit testing.

[TestClass]
public class ContactsControllerTests
{
    MockRepository repository;
    ContactsController contactsApi;

    [TestInitialize]
    public void InitializeForTests()
    {
        repository = new MockRepository();
        contactsApi = new ContactsController(repository);
    }
}

Let us test the GetContactsListAsync method first. Testing this method seems to be straight forward, as it returns either a plain generic list or throws an exception. But the test method can’t just return void like other tests, as the method is asynchronous. To test an asynchronous method, the test method should also be made asynchronous and return a Task. Following test checks if the controller action returns a collection of length 4:
[TestMethod]
public async Task GetContacts_Should_Return_List_Of_Contacts() 
{
    var contacts = await contactsApi.GetContactsListAsync();
    Assert.AreEqual(contacts.Count(), 4);
}

If the repository encounters an exception, the exception is re-thrown from the GetContactsListAsync method as well. This case can be checked using the ExpectedException attribute.
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public async Task GetContacts_Should_Throw_Exception()
{
    repository.FailGet = true;
    var contacts = await contactsApi.GetContactsListAsync();
}

Now let’s test the GetContactsHttpActionResultAsync method. Though this method does the same thing as the previous method, it doesn’t return the plain .NET objects. To test this method, we need to extract the result from the IHttpActionResult object obtained from the action method. Following test checks if the action result contains a collection when the repository is able to fetch results. Return type of Ok() method used above is OkNegotiatedContentResult. IHttpActionresult has to be converted to this type to check for the result obtained:
[TestMethod]
public async Task GetContactsHttpActionResult_Should_Return_HttpResult_With_Contacts()
{
    var contactsResult = await contactsApi.GetContactsHttpActionResultAsync() as OkNegotiatedContentResult<IEnumerable<Contact>>;

    Assert.AreEqual(contactsResult.Content.Count(), 4);
}

Similarly, in case of error, we are calling InternalServerError() method to return the exception for us. We need to convert the result to ExceptionResult type to be able to check the type of exception thrown. It is shown below:
[TestMethod]
public async Task GetContactsHttpActionResult_Should_Return_HttpResult_With_Exception()
{
    repository.FailGet = true;
    var contactsResult = await contactsApi.GetContactsHttpActionResultAsync() as ExceptionResult;
    Assert.IsInstanceOfType(contactsResult.Exception,typeof(InvalidOperationException));
}

Happy coding!

Wednesday, 4 December 2013

Invoking Angular JS Filters from Controller

In my post on Filtering and Sorting data using Angular JS, I got a comment requesting for a post on calling filters in a controller. We will see how to achieve the same in this post.

There are two ways to invoke filters from controllers in Angular JS. One approach is using the $filter service and the other is directly injecting the filters into the controller. Let’s see each of these cases.

Using $filter service
The $filter service is a provider that accepts name of a filter and returns the filter function. Once the function is obtained, we can pass in the required parameters. Following is the syntax:

$filter(‘filterName’)(params);

Let’s invoke one of the most used filters, orderBy using $filter to sort a list of items based name. After getting the filter function, we need to pass the source array and sort expression to the filter function. Following statement shows this:

$scope.items = $filter('orderBy')(itemsArray, "Name")

To apply multiple filters, we can pass result of a filter as parameter to another filter. Following snippet applies a filter condition on the sorted list obtained above:
$scope.items = $filter('filter')($filter('orderBy')(itemsArray, "Name"), "a")

The filter condition and sort expression passed into the above filters can be any dynamic values as well. A custom filter can also be called using the same syntax. Say, rupee is a filter I wrote to display my currency in rupee format; we can invoke the filter as:
$scope.totalPrice= $filter('rupee')(totalPrice);

Getting filters injected into the controller
Filters can be injected into the controller, but name of the filter to be specified in the controller argument should be appended with the word “Filter”.

app.controller('MyCtrl', function(orderByFilter){  //injects the orderBy filter into the controller
});

As we have a reference to the filter available in the controller, we can invoke the filter directly from here.
$scope.items= orderByFilter(itemsArray, "Name");

The result obtained can be passed into another filter to get combined result.
$scope.items = filterFilter(orderBy(itemsArray, "Name"), "a");

Same syntax can be used to inject and use a custom filter as well. I have put together a sample on jsfiddle covering the above concept: Happy coding!

Tuesday, 3 December 2013

Using External Login Providers with ASP.NET Identity System

In last post, we saw how simple the new Identity system in ASP.NET is and we explored the code generated by the Visual Studio template for handling local user accounts. In this post, we will see how easy it is to use an external login provider with the identity system.

Allowing users to use an external provider to login to a website has several advantages. It includes:

  1. Your application doesn’t need to store user names and passwords of the users using external login
  2. Almost all of the external login providers have secured logging page, using HTTPS
  3. The user doesn’t need to register to your site and so he/she doesn’t need to remember another set of user name and password


The Startup.Auth.cs file contains a block of commented code for external login providers. The providers include Google, Microsoft, Twitter and Facebook.

// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
//    clientId: "",
//    clientSecret: "");

//app.UseTwitterAuthentication(
//   consumerKey: "",
//   consumerSecret: "");

//app.UseFacebookAuthentication(
//   appId: "",
//   appSecret: "");

//app.UseGoogleAuthentication();

Out of these four providers, Google is the easiest provider to configure and use. It is as easy as just uncommenting the last statement in the above commented snippet. For other providers, we need to visit developer help websites of the third parties and input details of the application to get the keys. Pranav Rastogi documented these steps for us; they are available on Web Development Tools Blog on MSDN.

I enabled Google and Twitter in my application. The login page shows up buttons to use these providers.

After logging in using one of the external services, the application would ask the user to set a local user name. The user can optionally also set a local password for the account. Once the login at the external provider is successful, the user would be directed to ExternalLoginCallback. Following is the code inside this action method:
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{         
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }

    // Sign in the user with this external login provider if the user already has a login
    var user = await UserManager.FindAsync(loginInfo.Login);
    if (user != null)
    {
        await SignInAsync(user, isPersistent: false);
        return RedirectToLocal(returnUrl);
    }
    else
    {
        // If the user does not have an account, then prompt the user to create an account
        ViewBag.ReturnUrl = returnUrl;
        ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
    }
}
It does the following:

  1. Checks if the external login is successful. If the login has failed, the user is directed to the login page
  2. Once the login is successful, it checks if the logged in user already has a local username in the application. If the user doesn’t have one, the application prompts the user to create one
  3. If the user already has an account, the application directs the user to the return URL

To identify the user when he/she comes back and logs in using the same third party account, the identity system maintains details in the following two tables:

  1. AspNetUsers: It is the same table that holds details of local users. By default, external user IDs would be created with empty passwords.
  2. AspNetUserLogins: Holds user ID, name of the external provider and a provider key

The code of creating these records can be found in the ExternalLoginConfirmation action method of the AccountController. Following is the snippet that adds the records:

var info = await AuthenticationManager.GetExternalLoginInfoAsync();
if (info == null)
{
    return View("ExternalLoginFailure");
}
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user);
if (result.Succeeded)
{
    result = await UserManager.AddLoginAsync(user.Id, info.Login);
    if (result.Succeeded)
    {
        await SignInAsync(user, isPersistent: false);
        return RedirectToLocal(returnUrl);
    }
}

The AuthenticationManager.GetExternalLoginInfoAsync called above is a generic method and it provides just the data needed to identify the user. The returned value contains default user name, name of the third party provider and an authentication ID. It doesn’t provide vendor specific details about a user. To get more details from the vendor, we need to use the AuthenticateAsync method.
var vendorResult = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

Following screenshot shows the details obtained after logging in using twitter. If you inspect the value returned from Google, you will find e-mail ID of the user in the details, you may use it as the default username for the application as well.

Happy coding!