1. ホーム
  2. javascript

[解決済み] Angular ui ルータのユニットテスト(ステートからURLへ)

2023-08-20 09:08:16

質問

Angular uiルータで構築された私のアプリケーションのルータをユニットテストするのに苦労しています。私がテストしたいのは、状態の遷移が適切にURLを変更するかどうかです (後でもっと複雑なテストがありますが、これは私が始めているところです)。

以下は、私のアプリケーションのコードの関連する部分です。

angular.module('scrapbooks')
 .config( function($stateProvider){
    $stateProvider.state('splash', {
       url: "/splash/",
       templateUrl: "/app/splash/splash.tpl.html",
       controller: "SplashCtrl"
    })
 })

そして、テスト用のコード。

it("should change to the splash state", function(){
  inject(function($state, $rootScope){
     $rootScope.$apply(function(){
       $state.go("splash");
     });
     expect($state.current.name).to.equal("splash");
  })
})

Stackoverflowの同様の質問(および公式のuiルータのテストコード)では、$state.goの呼び出しを$applyでラップすれば十分であることが示唆されています。しかし、私はそれを行い、状態はまだ更新されません。$state.current.nameは空のままです。

どのように解決するのですか?

私もこの問題に直面していましたが、ようやく方法がわかりました。

以下は状態のサンプルです。

angular.module('myApp', ['ui.router'])
.config(['$stateProvider', function($stateProvider) {
    $stateProvider.state('myState', {
        url: '/state/:id',
        templateUrl: 'template.html',
        controller: 'MyCtrl',
        resolve: {
            data: ['myService', function(service) {
                return service.findAll();
            }]
        }
    });
}]);

以下のユニットテストは、URLとパラメータをテストし、それ自身の依存性を注入するリゾルブを実行することをカバーします。

describe('myApp/myState', function() {

  var $rootScope, $state, $injector, myServiceMock, state = 'myState';

  beforeEach(function() {

    module('myApp', function($provide) {
      $provide.value('myService', myServiceMock = {});
    });

    inject(function(_$rootScope_, _$state_, _$injector_, $templateCache) {
      $rootScope = _$rootScope_;
      $state = _$state_;
      $injector = _$injector_;

      // We need add the template entry into the templateCache if we ever
      // specify a templateUrl
      $templateCache.put('template.html', '');
    })
  });

  it('should respond to URL', function() {
    expect($state.href(state, { id: 1 })).toEqual('#/state/1');
  });

  it('should resolve data', function() {
    myServiceMock.findAll = jasmine.createSpy('findAll').and.returnValue('findAll');
    // earlier than jasmine 2.0, replace "and.returnValue" with "andReturn"

    $state.go(state);
    $rootScope.$digest();
    expect($state.current.name).toBe(state);

    // Call invoke to inject dependencies and run function
    expect($injector.invoke($state.current.resolve.data)).toBe('findAll');
  });
});