简体   繁体   English

如何使用Jasmine模拟链式承诺?

[英]How to mock chained promises using Jasmine?

I am writing a unit test to a method that contains this piece of code: 我正在为包含这段代码的方法编写单元测试:

Name.get($scope.nameId).then(function(name){
    Return name;
}).then(doSomething);

The function doSomething(name) looks like this. function doSomething(name)看起来像这样。

function doSomething(name){
    addNametoList(name);
}

I don't need to test this part of the code. 我不需要测试这部分代码。 Since I can't just ignore it in my test (or can I?), I need to mock it. 既然我不能在我的测试中忽略它(或者我可以吗?),我需要嘲笑它。 I mocked the first promise 我嘲笑了第一个承诺

 spyOn(mockName, 'get').and.returnValues($q.resolve({"Mike"})); 

and thought that it would propagate through the second then(doSomething) but name is undefined in function addNametoList . 并认为它将传播通过第二个then(doSomething)name在函数addNametoList undefined

I think I have to also mock doSomething but I have no idea how to chain them together. 我想我也要模仿doSomething但我不知道如何将它们连在一起。

I don't need to test this part of the code. 我不需要测试这部分代码。 Since I can't just ignore it in my test (or can I?), I need to mock it. 既然我不能在我的测试中忽略它(或者我可以吗?),我需要嘲笑它。 I mocked the first promise 我嘲笑了第一个承诺

IMO, there is no need to test such setups as a whole. IMO,没有必要测试这样的设置作为一个整体。 Test each unit individually. 单独测试每个单元。

For example 例如

A = () => {
  ...
}

B = () => {
  ...
}

C = () => {
  ...
}

Now we have F, which calls AB & C 现在我们有F,它叫AB&C

F = () => A(B(C))

Or in your case 或者在你的情况下

F = () => A().then(B).then(C)

We can test F, but it will require some setup, and be fragile. 我们可以测试F,但它需要一些设置,并且很脆弱。 Its better to test A, B & C (which give at a proper coverage for F) and ignore F. 最好测试A,B和C(给予F适当的覆盖)并忽略F.

Your (partial) controller code 你的(部分)控制器代码

$scope.list = [];

function addNameToList(name) {
  $scope.list.push(name);
}

function doSomething(name){
  addNametoList(name);
}

$scope.functionToTest = function() {
  Name.get($scope.nameId).then(function(name){
    return name;
  }).then(doSomething);
};

Your test 你的考试

it('should add the name to the list when Name.get() is resolved', function() {
  // Arrange
  var getDeferred = $q.defer();
  spyOn(mockName, 'get').and.returnValue(getDeferred.promise);

  // Act
  $scope.functionToTest();
  getDeferred.resolve('some name that should be in the list');
  $scope.$apply();

  // Assert
  expect($scope.list).toEqual(['some name that should be in the list']);
});

Comment 评论

Note that the following part of your code accomplishes nothing, and can be removed without affecting anything. 请注意,代码的以下部分不会完成任何操作,并且可以在不影响任何内容的情况下删除。

.then(function(name){
  return name;
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM