【问题标题】:How do I mock a method making an AJAX call?如何模拟进行 AJAX 调用的方法?
【发布时间】:2018-04-21 07:06:23
【问题描述】:

我正在尝试为我的 Angular 应用程序编写一些测试,并且我想模拟一个方法,这样我就不会对服务器进行实际调用。

这是我在 grid.service.ts 中的方法:

     loadAccountListPromise(id: string) {
        let promise = new Promise((resolve, reject) => {
            this.http.get(`${this.baseUrl}`)
                .toPromise()
                .then(
                (data) => {
                    this.results = this.formatData(data.json());
                    resolve(this.results);
                },
                (msg) => {
                    reject(msg);

                }
                );
        });
        return promise;

    }

到目前为止,我已经尝试按照官方角度测试指南编写类似的内容。在我的 grid.service.spec.ts 我有:

it('loadAcountListPromise should return Promise', () => {

            let someHttp;

            spyOn(myInnergridService, 'loadAccountListPromise').and.callThrough();

            myInnergridService.loadAccountListPromise(someHttp).then(
                ( response ) => { expect( response ).toBe( jasmine.any(Promise) );
            });
        });

在这里,我正在监视该方法,但通过调用.callThough(),我正在使用实际的实现,从而对服务器进行真正的 AJAX 调用。我想避免这种情况并伪造 GET 请求以进行测试。我该怎么做?

【问题讨论】:

    标签: javascript ajax angular unit-testing karma-jasmine


    【解决方案1】:

    首先,测试台:

    beforeEach(() => {
      TestBed.configureTestingModule({
        imports: [HttpModule],
        providers: [
          YourService,
          // ... Other services
          { provide: XHRBackend, useClass: MockBackend }
        ]
      });
    });
    

    然后,在每个测试中(或在 beforeEach 中):

    it('testing http calls ...', inject([YourService, XHRBackend], (service: YourService, http: MockBackend) => {
      let cnt: MockConnection;
      let response = { contenu: 'anything you want here' };
      http.connections.subscribe((connection: MockConnection) => {
        cnt = connection;
        // Response (CHOOSE ONE)
        connection.mockRespond(new Response(new ResponseOptions({
          body: JSON.stringify(response)
        })));
        // Error (CHOOSE ONE)
        connection.mockError(new Error('error'));
      });
    
      let goodCall = (method, url) => {
        expect(cnt.request.method).toBe(method);
        expect(cnt.request.url.endsWith(url)).toBe(true);
      };
    
      service.method().subscribe(res => goodCall(RequestMethod.Get, 'params/search'));
    }));
    

    有不懂的可以追问!

    【讨论】:

    • 哦,对于关键字的导入:import { HttpModule, Http, Response, ResponseOptions, RequestOptions, Headers, XHRBackend, RequestMethod } from '@angular/http';
    • 第二次导入(抱歉,我做了单独的 cmets 以便更清楚):import { MockBackend, MockConnection } from '@angular/http/testing';
    • 谢谢,但这一次有点多...当您调用 .method 这是我的 loadAccountListPromise() 方法时,正确。 (RequestMethod.Get, 'params/search') 是什么? RequestMethod 也是我的方法吗?另外,我将如何测试值类型?我想我上面的规范不再适用:(
    • method() 是进行您要测试的 http 调用的方法。 MyService 是...您的服务,您可能猜到了 :D 如果您看,对于最后一部分,我在调用该方法之前创建了一个函数,称为 GoodCall :它需要一个 HTTP 方法 (GET, PUT . ..) 和一个端点作为参数,并查看该方法是否使用正确的方法调用了正确的端点。在这里,我测试method 是否在以params/search 结尾的端点上创建http.get (RequestMethod.Get)。这样就更容易了,因为您只需调用在同一测试中进行 http 调用的方法!
    • 是的,这就是我假设看到的上面 :) 。我现在要试试。
    猜你喜欢
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    相关资源
    最近更新 更多