잊지 않겠습니다.

이번에는 Controller입니다. Controller는 view에서의 사용자의 action에 따른 scenario가 정해지게 됩니다. scenario에 따른 test code를 작성해주는 것이 가장 좋은 test code가 됩니다.
* page가 처음 load되면 list가 호출되어 기본 Data가 Loading된다. (AsService.list()가 호출)
* search button을 click시, list() method가 호출된다. (AsService.list()가 호출)
* startDate/endDate 값이 변경되면 list method가 호출된다.
* save button을 click시, confirm box가 표시되며, input값이 모두 정상적으로 입력되어 있지 않다면 error가 표시된다.

첫 case부터 시작해보도록 하겠습니다.

page가 처음 load되면 list() method가 호출된다.

page가 처음 load되는 것은 controller가 처음 생성되는 것을 의미합니다. 이는 beforeEach()에 대한 test code가 필요한 것을 의미합니다. list가 호출이 될 때, REST API를 호출하는 것을 가정하고 있기 때문에 REST API의 응답에 대한 mock response를 넣어주는 것이 필요합니다.

controller를 생성하기 위한 beforeEach와 createController 의 코드는 다음과 같이 구성될 수 있습니다.

  beforeEach(inject(function ($controller, $rootScope, _DateService_, $httpBackend) {
    httpBackend = $httpBackend;
    scope = $rootScope.$new();
    DateService = _DateService_;
    controller = $controller;
    OmAsListCtrl = createController();
  }));

  var createController = function() {
    var response = {"ok":true,"message":"api call completed","date":1413173458673,"data":[{"request":"김요청자","operators":"","requestPhoneNumber":"0212342341","receiptDate":"2014-08-27","name":"오피스를 더 좋게 해주세요.","receiptionPhoneNumber":"03121342134","location":"없음","id":"30221","receiption":"김접수자","departments":"관리팀,건축팀,관제팀,기계팀,소방팀","department":"-","status":"접수"},{"request":"박네임","requestPhoneNumber":"01015263748","departmentId":"0401","receiptDate":"2014-05-05","name":"13층 환기 안됨","receiptionPhoneNumber":"01056781234","location":"13층","id":"6","receiption":"이성명","departments":"관리팀,기계팀","department":"관리팀","status":"민원완료"}]};
    httpBackend.when('GET', /\/fms-api\/om\/as\/list?\W*/).respond(response);
    var ctrl = controller('OmAsListCtrl', {
      $scope: scope
    });
    scope.$digest();
    httpBackend.flush();
    expect(scope.items.length).not.toBe(0);
    return ctrl;
  };

scope.items의 갯수를 확인하고, 정확히 데이터가 matching되고 있는 것을 확인하면 load의 test code는 완료됩니다.

search button을 click시, list() method가 호출된다.

list button을 click하는 것은 $scope.list()가 호출되는 것을 의미합니다. 호출후에 items의 갯수를 확인해보는 것이 가장 쉬운 확인 방법입니다. test를 보다 쉽게 작성하기 위해서 list를 호출하기 전에 items를 초기화 시켜버린 후에 list를 호출한 후의 값을 비교해보면 확실히 알 수 있을것입니다.

  it('search button을 click시, list() method가 호출된다.', function() {
    scope.items = [];
    var response = {"ok":true,"message":"api call completed","date":1413173458673,"data":[{"request":"김요청자","operators":"","requestPhoneNumber":"0212342341","receiptDate":"2014-08-27","name":"오피스를 더 좋게 해주세요.","receiptionPhoneNumber":"03121342134","location":"없음","id":"30221","receiption":"김접수자","departments":"관리팀,건축팀,관제팀,기계팀,소방팀","department":"-","status":"접수"},{"request":"박네임","requestPhoneNumber":"01015263748","departmentId":"0401","receiptDate":"2014-05-05","name":"13층 환기 안됨","receiptionPhoneNumber":"01056781234","location":"13층","id":"6","receiption":"이성명","departments":"관리팀,기계팀","department":"관리팀","status":"민원완료"}]};
    httpBackend.when('GET', /\/fms-api\/om\/as\/list?\W*/).respond(response);
    scope.list();
    httpBackend.flush();
    expect(scope.items.length).not.toBe(0);
  });

startDate/endDate값이 변경되면 list method가 호출된다.

이는 spyOn을 이용하면 쉽게 처리가 가능합니다. 다음과 같은 test code를 작성할 수 있습니다.

  it('startDate가 변경되면, list가 호출되어야지 된다.', function() {
    spyOn(scope, 'list');
    scope.searchItem.startDate = '2015-05-01';
    scope.$digest();
    expect(scope.list).toHaveBeenCalled();
  });

  it('endDate가 변경되면, list가 호출되어야지 된다.', function() {
    spyOn(scope, 'list');
    scope.searchItem.endDate = '2015-05-01';
    scope.$digest();
    expect(scope.list).toHaveBeenCalled();
  });

save button을 click시, confirm이 표시되고, confirm true인 경우에 AsService.regist method가 호출된다.

confirm, alert은 browser가 제공하는 base dialog method입니다. 만약에 우리가 test code를 실행할때마다 dialog가 나오고, 그걸 수동으로 눌러줘야지 된다면 이는 매우 걸리적 거리는 일이 됩니다. 따라서, 이 method들을 override 시킬 필요가 있습니다. angularJS는 이를 위해서 $window를 제공하고 있습니다. 우리가 $window.confirm, $window.alert method를 override 시켜서 사용하면 confirm에서 항상 true만 선택하게 할 수 있습니다.

  beforeEach(inject(function ($controller, $rootScope, _$routeParams_, _$location_, _$window_) {
    routeParams = _$routeParams_;
    routeParams.id = '10';
    scope = $rootScope.$new();
    controller = $controller;
    window = _$window_;
    window.confirm = function(message) {
      console.log(message);
      return true;
    };
  }));

routeParam의 값에 따라 다른 동작을 하는 controller의 테스트

위 scenario에 없는 parameter값에 따라 다른 동작을 하는 controller를 test하는 방법입니다. 이는 기본적으로 $routeParam에 값을 설정시키고 나서 controller를 생성시켜주면 됩니다. 다음과 같은 test code pattern을 적용하면 됩니다.

  function createCtrl(ymd, type) {
    if(ymd) {
      routeParams.ymd = ymd;
    }
    if(type) {
      routeParams.type = type;
    }

    ctrl = controller('EmDailymeterListCtrl', {
      $scope: scope,
      $routeParams: routeParams,
      Dailymeterservice: service
    });
    if(ymd == null || type == 'list') {
      httpBackend.expectGET(/\/fms-api\/em\/dailymeter\/list?\W*/).respond(200, {});
    } else {
      httpBackend.expectGET(/\/fms-api\/em\/dailymeter\/new?\W*/).respond(200, {});
    }
    scope.$digest();
    httpBackend.flush();
    return ctrl;
  }


Posted by Y2K
,