4

我正在构建一个应用程序原型并尝试模拟 REST Web 服务。

这是我的代码:

var mock = angular.module('mock', ['ngMockE2E']);
mock.run(function($httpBackend){
    users = [{id:1,name:'John'},{id:2,name:'Jack'}];
    $httpBackend.whenGET('/users').respond(users);
    $httpBackend.whenGET(new RegExp('\\/users\\/[0-9]+')).respond(users[0]);
}

一切正常,我的资源 User.query() 返回所有用户,而 User.get({id:1}) 和 User.get({id:2}) 返回同一个用户(John)。

现在为了改进我的原型,我想返回合适的用户,匹配好的 id。

我在角度文档中阅读了我应该能够用函数替换 RegExp URI。这个想法是从 url 中提取 id 以在响应方法中使用它。然后我尝试了这个:

$httpBackend.whenGET(new function(url){
    alert(url);
    var regexp = new RegExp('\\/users\\/([0-9]+)'); 
    id = url.match(regexp)[1];  
    return regexp.test(url);
}).respond(users[id]);

问题是 url 参数始终未定义。有什么想法可以实现我的目标吗?

4

2 回答 2

6

通过使用new function(url)您的应用程序尝试从您的匿名函数实例化一个新对象,并将该新对象作为$httpBackend.whenGET()调用的第一个参数传递。
当然,在调用时whenGET()没有提供 URL,因此它始终是未定义的。

您应该传递函数本身(而不是使用该函数实例化的对象)。例如:

$httpBackend.whenGET(function (url) {
  ...
}).respond(users[id]);

更新:
经过更多挖掘,结果证明将函数作为第一个参数传递给的选项whenGET已添加到版本1.3.0-beta.3中。您正在阅读的文档可能是指最新的 beta 版本,而您使用的是早期版本。
(请注意,即使版本 1.3.0-beta.1 和 2 也没有提供此选项。)

无需赘述,负责验证匹配 URL 的是MockHttpExpectationmatchUrl方法:

function MockHttpExpectation(method, url, data, headers) {
  ...
  this.matchUrl = function(u) {
    if (!url) return true;
    if (angular.isFunction(url.test)) return url.test(u);
    if (angular.isFunction(url)) return url(u);   // <<<<< this line does the trick
    return url == u;
  };

该行if (angular.isFunction(url)) return url(u);提供了直接传递函数的选项,并在 1.3.0-beta.3 版本中添加(如前所述)。但是,如果您仍想将函数传递给以前的 AngularJS 版本,则可以通过为对象提供test方法来“欺骗” Angular 相信您传递了 RegExp。
即替换:

.whenGET(function (url) {...})

和:

.whenGET({test: function (url) {...}})

另请参阅这个简短的演示

于 2014-03-24T20:35:22.453 回答
3

我通过在响应部分而不是 when 部分中使用函数找到了解决方案:

$httpBackend.whenGET(new RegExp('\\/users\\/[0-9]+')).respond(
    function(method, url){
        var regexp = new RegExp('\\/users\\/([0-9]+)');
        var mockId = url.match(regexp)[1];
        return [200, users[mockId]];
    }
});
于 2014-03-25T10:39:15.370 回答