Returning values from a mocked angular service and calling through

时间:2016-04-15 15:05:26

标签: javascript angularjs jasmine karma-runner

I am having some problems figuring out how to write tests correctly for a controller method that relies on calling an Angular service and returning a certain value, but, I need to be able to test the code within the .then() function after.

Here is the basic idea:

// Controller

$scope.myMethod = function() {
    methodName.connect().then(
        function(returnValue) {
            if (returnValue.prop === 1) {
                $scope.callMade = true;
                $rootScope.$emit('callWasMade');
            }
        },
        function() {
            $rootScope.$emit('callWasNotMade');
        }
    );
};

So I want to test the call to the method on the $scope, call the methodName.connect() function but I want to mock a response (overwriting returnValue) but still have the function run as normal. Something like:

// Test

describe('connecting to method', function() {
    it('should do nothing when returnValue.prop does not equal 1', function() {
        spyOn(methodName, 'connect').and.returnValue({ prop: 2 });
        scope.myMethod();
        expect(scope.callMade).toBeFalsy();
    });

    it('should pass when returnValue.prop does equal 1', function() {
        spyOn(methodName, 'connect').and.returnValue({ prop: 1 });
        scope.myMethod();
        expect(scope.callMade).toBeTruthy();
    });
});

Except this returns

undefined is not a constructor (evaluating 'methodName.connect().then') (...)

How can I control the output from methodName.connect in this way?

Thanks.

1 个答案:

答案 0 :(得分:0)

正如您所说,methodName是一项服务。所以只需在注入的控制器中模拟这个服务。

另外,我对你的控制器有疑问。为什么myMethod附加到范围,而不是控制器本身(例如:myMethod = function() {})?

以下代码应该有效:

describe('connecting to method', function() {
  beforeEach(inject(function($controller, $rootScope) {
    // create a mock service attached to controller
    methodName = {
      connect: function () {
      }
    };

    spyOn(methodName, 'connect').and.returnValue({ prop: 2 });

    scope = $rootScope.$new();
    controller = $controller('yourCtrl', {
      $scope: scope,
      methodName : methodName 
    });
  }));

  it('should do nothing when returnValue.prop does not equal 1', function() {
    // here I consider myMethod is a method of controller, but not of the scope
    myMethod();
    expect(scope.callMade).toBeFalsy();
  });
});