我有一项服务,我想在角4打字茉莉花中进行单元测试。
现在,http
正在执行post
,但它会返回一个标识,但是它没有发送任何内容。
我想要有良好的代码覆盖率,但我不明白如何完成这个嘲弄声明。
此处是我的服务文件中http post的方法
addSession() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.url, JSON.stringify({}), options)
.map((response: Response) => response.json());
}
然后是SPEC FILE ,我没有得到真正的测试内容,我想假设我从服务http帖子收到了一个号码,响应应该是{{ {1}}
规格
000000014
答案 0 :(得分:6)
为了达到你想要的效果,你需要的模拟是一个简单的函数,返回与POST正常相同的函数;另一件事是你的测试不应该是真正的服务器,所以你需要这样的东西(你可能需要添加其他依赖项):
import { HttpModule } from '@angular/http';
import { TrackerFormService } from './tracker-form.service'
import { Observable } from 'rxjs/Observable'
describe('TrackerFormService', () => {
// Mock the service like this and add all the functions you have in this fashion
let trackerFormService: TrackerFormService,
mockService = {
addSession: jasmine.createSpy('addSession').and.returnValue(Observable.of('your session object mock goes here'))
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [{
provide: TrackerFormService,
useValue: mockService
}]
});
});
// Do this trick to inject the service every time, and just use `service` in your tests
beforeEach(inject([TrackerFormService], (trackerFormService) => {
service = trackerFormService;
}));
describe('addSession', () => {
it('add session ', () => {
let fakeResponse = null;
// Call the service function and subscribe to it to catch the fake response coming from the mock.
service.addSession().subscribe((value) => {
// in here value will be whatever you put as returnValue (remember to keep the observable.of())
fakeResponse = value;
});
// expects as in any test.
expect(fakeResponse).toBeDefined();
expect(fakeResponse).toBe('your session object mock goes here');
});
});
});
答案 1 :(得分:0)
使用Angular 4.3,HttpClient服务取代了Http,并提供了一种模拟HTTP请求的简便方法。它在官方页面上有详细记录:https://angular.io/guide/http
答案 2 :(得分:0)
你设置测试/模拟的方式,你可以伪造回调,并检查你得到了你期望的结果。通过这样做,您将测试模拟响应将由map语句正确转换。有了你的间谍,你还可以检查post方法的调用方式。这将检查选项是否符合您的预期。
但在我看来,这是一个相当复杂的解决方案。我倾向于通过拆分方法来避免模拟和间谍,所以每种方法都只做一件事。因为你的addSession方法目前正在做三件不同的(但依赖于逻辑的)事情:
如果你在三个方法中打破方法,你可以在单独的测试中轻松测试方法#1和#3,方法#2只包含对http库的调用。这使您可以在不调用http库的情况下获得与上述相同的测试值。
现在方法#2怎么样......它还没有经过测试,我认为没有理由对它进行测试。因为你没有写那段代码。此外,如果您使用angulars http模块,我相信他们自己也有可靠的单元测试。
您的服务响应应该已经包含在额外的集成测试中,运行频率较低,检查服务api仍然会返回您期望的内容。
如果您真的希望代码覆盖率中有一行绿色,那么您可以选择使用名为nock的库。 Nock将拦截您的应用程序将导致的所有xhr流量。在测试文件中,您可以使用nock对象将xhr请求映射到模拟响应。
var scope = nock('http://myapp.iriscouch.com')
.post('/users', {
username: 'pgte',
email: 'pedro.teixeira@gmail.com'
})
.reply(201, {
ok: true,
id: '123ABC',
rev: '946B7D1C'
});

复制自:https://www.npmjs.com/package/nock
有关一般测试的参考和其他信息以及我建议观看测试的数量 "预算现实"作者Justin Searls
答案 3 :(得分:-2)
http服务请求的示例测试用例
describe('Forgot Password Controller', function () {
var $controller,
$httpBackend,
$q,
$rootScope,
$state,
controller,
scope,
accountProvider;
beforeEach(module('app'));
beforeEach(inject(function (_$injector_, _$controller_, _$rootScope_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
$httpBackend = _$injector_.get('$httpBackend');
$state = _$injector_.get('$state');
$q = _$injector_.get('$q');
accountProvider = _$injector_.get('accountProvider');
scope = _$rootScope_.$new();
controller = $controller(app.controllers.forgotPassword, {
$state: $state,
accountProvider: accountProvider
});
}));
afterEach(function () {
$httpBackend.verifyNoOutstandingRequest();
$httpBackend.verifyNoOutstandingExpectation();
});
describe('forgot password submission', function () {
it('Can submit a forgot password request successfully', function () {
$httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(200);
spyOn($state, 'go');
controller.form = { emailAddress: 'aks@gmail.com' };
controller.submit();
expect(controller.submitting).toBe(true);
$httpBackend.flush();
expect(controller.submitting).toBe(false);
expect($state.go).toHaveBeenCalledWith('login', { successMessage: 'An email sent to ' + controller.form.emailAddress + ' contains instructions for resetting your password.' });
});
it('Can handle when a user is not found when submitting a forgot password request', function () {
$httpBackend.expectPOST(app.env.EDGE_SERVICE_PATH + '/events/requestPasswordReset').respond(404);
spyOn($state, 'go');
controller.form = { emailAddress: 'aks@gmail.com' };
controller.submit();
expect(controller.submitting).toBe(true);
$httpBackend.flush();
// We intentionally want to make it appear to the user that the password reset email was sent even when a user
// does not exist, to help hide info about which users exist in the system
expect(controller.submitting).toBe(false);
expect($state.go).toHaveBeenCalledWith('login', { successMessage: 'An email sent to ' + controller.form.emailAddress + ' contains instructions for resetting your password.' });
});
it('Can handle unexpected errors from submitting a forgot password request', function () {
$httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(500);
controller.submit();
$httpBackend.flush();
expect(controller.errors.unexpectedError).toBe(true);
});
it('Can handle 422 validation errors from submitting a forgot password request', function () {
var responseData = {
fieldErrors: {
username: [{code: 'error'}, {code: 'required', message: 'This is required.'}]
}
};
$httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(422, responseData);
controller.submit();
$httpBackend.flush();
expect(controller.errors.validationErrors).toBe(true);
expect(controller.errors.fieldErrors).toEqual(responseData.fieldErrors);
});
it('Can handle 503 service unavailable from submitting a forgot password request', function () {
$httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(503);
controller.submit();
$httpBackend.flush();
expect(controller.errors.serviceUnavailable).toBe(true);
});
});
});