【问题标题】:Angular test using $httpBackend fails with "400 thrown" error使用 $httpBackend 的角度测试失败并出现“400 throwed”错误
【发布时间】:2015-05-10 07:22:30
【问题描述】:

几个小时以来,我一直在尝试使用 $httpBackend 测试我的 NewPostController。问题是每当我在响应中设置非 2xx 状态码时,测试都会失败。

NewPostController 有如下方法:

$scope.submit = function () {
  var newPost = $scope.newPost;
    PostService.insertPost(newPost).then(function (post) {
      $location.path("/my-posts");
    }, function (status) {
        $scope.form.$setPristine();
        $scope.error = status;
    });
};

我在测试失败路径时遇到问题:

it(...) {
  ...
  $scope.post.text = "";
  $httpBackend.expectPOST("/create-post", {"post":$scope.post}).respond(400);
  $scope.submit();
  $httpBackend.flush();
  expect($scope.error).toBeDefined();

  $scope.post.text = "This is a valid text.";
  $httpBackend.expectPOST("/create-post", {"post": $scope.post}).respond(200);
  $scope.submit();
  $httpBackend.flush();
  expect($location.path()).toBe("/my-posts");
});

测试失败并显示消息“400 throwed”(没有调用堆栈)。我尝试更改子测试的顺序,使用 whenPOST 而不是 expectPOST 并像在 Angular 文档 (https://docs.angularjs.org/api/ngMock/service/$httpBackend) 中那样组合这些方法,但没有成功。

请帮忙。

编辑:

现在,当我查看 PostService 时,“抛出 400”的来源是有道理的,但我预计错误将由 angular 处理。因为this article 的“处理嵌套服务调用中的问题”部分,我把它扔了。它应该是 deferred.resolve/reject 机制的较短版本。

this.insertPost = function (newPost) {
  return $http({
    method: "post",
    url: "/create-post",
    data: {
      post: newPost
    }
  }).then(function (res) {
      return (res.data);
  }, function (res) {
      throw res.status;
  });
};

【问题讨论】:

  • 发布 karma 的完整输出。并贴出 PostService 的代码。

标签: angularjs karma-runner karma-jasmine httpbackend


【解决方案1】:

这确实很奇怪,可能是 Angular 团队没有考虑到的。

当一个 Promise 被抛出拒绝时(正如你正在做的那样),角度 $exceptionHandler service 被调用并抛出异常。默认情况下,该服务只在浏览器控制台中记录异常。

但是在使用 ngMocks 时,this service 被替换为可以记录或重新抛出异常的模拟实现。默认模式是重新抛出,以便在抛出异常时使测试失败。

我的建议是避免使用 throw 来简单地拒绝一个承诺,从而替换

function (res) {
  throw res.status;
}

通过

function (res) {
  return $q.reject(res.status);
}

但是如果你真的想继续使用 throw,你也可以配置 mock exceptionHandler 来记录而不是重新抛出:

beforeEach(module(function($exceptionHandlerProvider) {
  $exceptionHandlerProvider.mode('log');
}));

【讨论】:

  • 非常感谢!我尝试了两种解决方案,它们都有效。你更倾向于使用 $q.reject 吗?我没有偏好。
  • 是的。我觉得 throw 应该用来表示错误(错误)而不是预期的情况。它不能很好地与单元测试一起使用的事实也表明应该使用 $q.reject() 。我还担心将 exceptionHandler 配置为 log 可能会使您的测试变得脆弱,并且可能会在不应该的情况下成功。
  • 这是有道理的。再次感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-22
  • 2015-09-19
  • 2019-05-27
  • 2020-12-28
  • 1970-01-01
相关资源
最近更新 更多