เริ่มต้นเขียน unit test กับ JavaScript AngularJS ตอนที่ 3 unit test controller

จากบทความสองตอนที่ผ่านมา เราได้ลองเขียน unit test ทดสอบการทำงานของ AngularJS service กันมาบ้างแล้ว

ในบทความนี้ เราจะมาลองเขียน unit test ทดสอบ controller กันครับ

โดยขั้นตอนต่างๆ เป็นดังนี้

  • สร้าง Angular controller
  • สร้าง unit test ทดสอบการทำงานของ controller
  • run unit test

สร้าง Angular controller

เราจะสร้าง weatherController โดยการเพิ่มเข้าไปใน file weatherApp.js ที่มีอยู่แล้ว แก้ไข weatherApp.js เป็นดังนี้

/src/weatherApp.js

app.controller('weatherController', function ($scope, weatherService) {

   $scope.cities = weatherService.getWeathers();

   $scope.cityNames = $scope.cities.map(function (city) {
       return city.name.toLowerCase();
   });

   $scope.search = function (cityName) {
       var cityIndex = $scope.cityNames.indexOf(cityName.toLowerCase());
       var city = $scope.cities[cityIndex];
       return city;
   };
});
  • weatherController มีการเรียกใช้งาน weatherService เพื่อขอข้อมูลอุณภูมิของเมืองทั้งหมดที่มีอยู่*
  • $scope.cities เก็บ array ของเมืองทั้งหมด โดยที่ค่าเหล่านี้ได้มาจากการเรียกใช้ weatherService อีกที
  • ใน weatherController มี function search ที่สำหรับค้นหา city object โดยการส่งชื่อเมืองเข้าไป เราจะใช้ city object ที่ return ออกมา เพื่ออ่านค่า temperature อุณหภูมิของเมืองนั้นๆ

สร้าง unit test ทดสอบการทำงานของ controller

สร้าง JavaScript file ไว้ใน folder spec ตั้งชื่อว่า weatherControllerSpec

เราต้องการทดสอบว่า function search นั้นทำงานได้ถูกต้่องหรือไม่ โดยเราจะส่งค่าชื่อเมือง bangkok เข้าไป แล้วได้ city object แล้วทดสอบที่มือชื่อเมืองและอุณหภูมิกลับมาว่าตรงกับที่ต้องการหรือไม่

เราลองเขียน code ลงใน weatherController.js เป็นดังนี้

/spec/weatherControllerSpec.js

describe('weatherController', function () {

    it('search bangkok should return Bangkok city', function () {

        //load module
        angular.mock.module('weatherApp');

        //get controller
        var controller = null;
        angular.mock.inject(function (weatherController) {
            controller = weatherController 
        });

    });
});

จากความรู้ในเรื่องการเขียน unit test AngularJS service เราทราบว่า เราเพียงระบุ parameter callback function ของ angular.mock.inject ให้ตรงกับชื่อ service ที่เราต้องการ Angular จะสร้าง service ให้เราอัตโนมัติ และนำไปใช้งานต่อได้เลย

บรรทัดที่ 10 วิธีการนี้ใช้ไม่ได้กับ controller ครับ เราไม่สามารถสร้าง controller ด้วยวิธีการนี้ได้ เราต้องใช้ผ่าน Angular controller service ด้วย parameter $controller

แล้วใช้ $controller service ตัวนี้สร้าง controller ที่เราต้องการ

แก้ไข weatherController.js เป็นดังนี้

/spec/weatherControllerSpec.js

describe('weatherController', function () {

   it('search bangkok should return Bangkok city', function () {

       //load module
       angular.mock.module('weatherApp');

       //get service
       var controllerService = null;
       angular.mock.inject(function ($controller) {
           controllerService = $controller;
       });

       var scope = {};
       var weatherController = controllerService('weatherController',
                                             {$scope: scope});

       var city = scope.search('bangkok');
       expect(city.name).toBe('Bangkok');
       expect(city.temp).toBe(32);
   });
});
  • Angular mock module จะสร้าง controller service เก็บไว้ในตัวแปร $scontroller แล้วเราก็ assign ไปเก็บไว้ที่ controllerService
  • เราใช้ controllerService สร้าง weatherController ส่ง argument เข้าไปดังนี้
    • ชื่อ controller string ที่ต้องการคือ weatherController
    • empty scrope object
  • เรียกใช้งาน function search และส่งค่าชื่อเมือง bangkok
  • ได้ city object กลับมา แล้วทดสอบว่าชื่อเมืองตรงกับ Bangkok และอุณหภูมิคือ 32 หรือไม่
  • สังเกตว่า weatherController มีการใช้งาน weatherService แต่เราไม่ต้องสร้าง weatherService ขึ้นมาเอง เพราะเมื่อเราสร้าง controller ผ่าน mock module service ต่างๆ ที่ controller ต้องการจะถูกสร้างให้อัตโนมัติ

run unit test cases

เปิด Windows command line หรือ UNIX terminal ไปที่ root folder ของ project นี้

แล้วพิมพ์

npm test

ผลลัพธ์การทำงาน

image 1

แสดงว่ามี test cases ผ่าน 3 cases แทนที่จะเป็น 1 เนื่องจาก Karam ได้ run test ที่ได้สร้างไว้จากตอนที่ 1 และ 2 ด้วย

ส่งท้าย ในตอนนี้ เราได้มาลองเขียน unit test กับ AngularJS controller กันแล้ว ผู้อ่านได้เห็นภาพการประยุกต์ใช้งานมากขึ้น ในตัวอย่างต่อไป เราจะลอง test $http service ทดสอบการเพื่อทดสอบ function ที่ต้องการดึงข้อมูลจาก server ว่าทำงานได้ถูกต้องหรือไม่

มีคำถามหรือข้อสงสัยใดๆ แนะนำมาได้เลยนะครับ

ขอบคุณครับ

download source code

เมื่อโหลดไปแล้วใช้คำสั่ง npm install package ต่างๆ ก็จะโหลดให้โดยอัตโนมัติครับ