Test Angular resolve method

2019-07-09 07:20发布

问题:

I have Angular with ui-router, so toResolve variable will be resolved in my SomeController

.state('some.state', {
      url: '/some',
      controller: 'SomeController',
      templateUrl: '/static/views/some-state.html',
      resolve: {
        toResolve: function(Resource) {
          return Resource.get(function(response) {
            return response;
          });
        },

But how to test this functionality with Jasmine? Let's suppose that I forget return statement, therefore the toResolve in my scope will be undefined.

回答1:

Use services to make resolvers efficiently testable (and also mockable in integration/e2e tests).

Note: Angular services are singletons, state/route resolvers are not.

If caching a resolution is expected, a resolver may be moved to factory service.

app.factory('someResolver', function(Resource) {
  return Resource.get(function(response) {
    return response;
  })
});
...

resolve: { toResolve: 'someResolver' },

On the other hand, if the resolver is expected to be evaluated on each route change, this may lead to undesirable app behaviour. In this case the appropriate recipe may be constant annotated function:

app.constant('someResolver', ['Resource', function(Resource) {
  return Resource.get(function(response) {
    return response;
  })
}]);

app.config(function (someResolver, ...) {
  ...
  resolve: { toResolve: someResolver },
  ...

Otherwise the specs may end encumbered with a pile of boilerplate code:

var toResolveFactory = $state.get('some.state').resolve.toResolve;
var toResolve = $injector.invoke(toResolveFactory);


回答2:

One good article on related topic is http://nikas.praninskas.com/angular/2014/09/27/unit-testing-ui-router-configuration/, but it's not the solution. One idea is to pass another object to resolve and then test that unit of code separately which is good when you're resolving a bunch of items.