使用Angular mock为Backendless开发加载JSON文件

时间:2014-01-04 00:29:19

标签: javascript ajax json angularjs angular-mock

我在单独的.js文件中为前端后端环境编写了这个小代码。只要有一个ajax调用myfile.json,我就需要/somelink

angular.module('myApp')
.config(function($provide) {
  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
})
.run(function($httpBackend, $http) {

  $httpBackend.whenGET('/somelink').respond(function(method, url, data) {
    $http({method: 'GET', url: '/somelink/myfile.json'})
    .success(function(data, status, headers, config) {
      return data;
    })
    .error(function(data, status, headers, config) {
    });

  });
});

但是这段代码不起作用并且给了我错误:

Error: Unexpected request: GET /somelink/myfile.json

有人可以帮我解决这个问题吗?

请注意,我不想直接调用$ http来获取代码中的.json文件,因为这会丢弃生产代码。这样做的目的是将此代码分别保留在后端开发中。

感谢。

更新1:

我补充说:

$rootScope.$apply(); 
$httpBackend.flush();

现在我还有另一个错误:Uncaught Error: No pending request to flush !

更新2:

玩完游戏后,我发现了一个小黑客。我把它放在.run()所有其他$ httpBackend模拟之前。此.js文件也必须放在所有控制器/服务/指令之前和app.js引导程序之后。

  var data;

  $.ajax({
    type: 'GET',
    async: false,
    url: '/somelink/myfile.json'
  }).success(function(res) {
    data = res;
  }).error(function(data) {
  });

然后这个:

$httpBackend.whenGET('/somelink').respond(data);

键是async: false,这样可以确保将JSON加载到变量data中。所有这些必须在其他对象触发并调用ajax事件之前发生。这只是前端后端开发的黑客攻击。生产时,当然会删除此.js文件。我不喜欢这么多是因为使用async: false和直接$.ajax()代替$http

5 个答案:

答案 0 :(得分:8)

以下为我工作没有任何黑客

$httpBackend.whenGET('/endpoint').respond($resource("/path/to.json").query());

礼貌https://groups.google.com/d/msg/angular/grbwk-VehDE/UBIho6qcmLMJ

答案 1 :(得分:4)

此问题的一个非常干净的解决方案是使用plain vanilla JavaScript,因为$httpBackend不会处理asynchronous请求。

此方法不需要jQuery代码。

$httpBackend.when('GET', 'http://localhost:3000/api/data').respond(getData());

function getData() {
               var request = new XMLHttpRequest();
               request.open('GET', '/db/myData.json', false);
               request.send(null);

               return [request.status, request.response, {}];
}

我得到了这个提示: https://stackoverflow.com/a/24287558/4742733

答案 2 :(得分:3)

我知道这是一个迟到的回应,但会分享我的经验,希望能为未来的同行提供一些帮助。

由于这个非常有用的blog post,我成功地实现了一个有效的模拟后端。

首先,我将所有端点作为常量放在一个位置,以便只定义它们一次,并在模拟的后端,在我的测试中显示它们,显然在所有负责AJAX调用的服务中。

angular.module('appName.urls', [])
 .constant('API_endpoints', {
   login: 'authentication/login',
   logout: 'authentication/logout',
   signUp: 'authentication/signup',
   userList: 'users/list'
 });

然后我将ngMockE2E添加为整个应用程序的依赖项。

angular.module('appName', [
  'ui.router',
   ... 
  'ngMockE2E'
])

然后我为实际的模拟后端创建了一个文件,让我们称之为fakeBackend.js并在index.html中引用。这个文件取自上面的链接,但这是我实现的一个简化示例(这里提供模拟登录):

angular.module('appName').run(function($httpBackend, API_endpoints) {

   var credentials = {
    email : 'a@a.a',
    password : '12345'
  };

  $httpBackend.whenPOST(API_endpoints.login)
              .respond(function(method, url, data) {

    var req = JSON.parse(data),
        res;
    // very light credential check...
    if(req.email === credentials.email && req.password === credentials.password ){
        // generate a successful response
        res = [200, {uuid:1}, {}];
    } else {
        // generate an error if credentials are wrong
        res = [400, {}, {}];
    }
    return res;
  });

   // Respond to all templates request
   // Every file in states/ folder will be served automatically
   $httpBackend.whenGET(/states\//).passThrough();
}):

另请注意,我的states文件夹中的所有内容都提供了最后一行,我的所有模板都驻留在该文件夹中。这显然是一个非常简单的例子,但博客文章作者也分享了一个非常详细和有用的plunkr

答案 3 :(得分:2)

我(以及其他许多人)在使用$ httpBackend进行测试时遇到了这个问题。我还没有将它用于后端开发。测试中的解决方案是:

AngularJS is opinionated AND hungry, so to make $http requests fire in a test, you must either $apply or $digest.

在我的测试中让$ http工作我必须

root.$apply(); 
httpBackend.flush();

也许这样的事情可以帮到你。

答案 4 :(得分:1)

@Aakash Shah使用原始javascript制作同步xhr请求的答案对我来说非常有效。这里有一些代码来澄清我如何概括它。

addMock('/ mocks / json / myjson.json',new RegExp('yada /.*/ getMyJson'));

    function addMock(jsonFilePath, urlToReplace) {
        $httpBackend.whenGET(urlToReplace)
            .respond.apply(this, getData(jsonFilePath)); // apply to put the parameters as args
    }

    function getData(jsonFilePath) {
        var request = new XMLHttpRequest();
        request.open('GET', jsonFilePath, false);
        request.send(null);

        return [request.status, request.response, {}];
    }