嗨,我正在为Angular 5应用程序编写单元测试用例。我在我的项目中使用了api。我正在为肯定和否定场景编写单元测试用例。我已经完成了积极的案例。我正在努力编写负面的测试案例。例如我有ngoninit方法将数据加载到网格。下面是我的代码段。
ngOnInit() {
this.loadTenantsData();
this.columns = [
{ prop: "index", name: '#', width: 30, headerTemplate: this.statusHeaderTemplate, cellTemplate: this.statusTemplate, resizeable: false, canAutoResize: false, sortable: false, draggable: false },
{ prop: 'tenantname', name: 'Tenant', cellTemplate: this.nameTemplate, width: 200 },
{ name: '', width: 80, cellTemplate: this.actionsTemplate, resizeable: false, canAutoResize: false, sortable: false, draggable: false }
];
}
下面是loadTenantsData方法。
private loadTenantsData() {
this.tenantService.getTenants().subscribe(results => this.onTenantDataLoadSuccessful(results), error => this.onTenantDataLoadFailed(error));
}
以下是我的租户服务。
getTenants(page?: number, pageSize?: number) {
return this.tenantEndpoint.getTenantsEndpoint<Tenant[]>(page, pageSize);
}
以下是我的租户终结点服务。
getTenantsEndpoint<T>(page?: number, pageSize?: number): Observable<T> {
return Observable.create(observer => {
var tenants = [{
'tenantid': 'bcdaedf3-fb94-45c7-b6a5-026ca4c53233',
'tenantname': 'BENZAAD.onmicrosoft.com'
}
];
if (!tenants) {
throw 'no tenants given'
}
observer.next(tenants);
});
}
下面是我的错误处理程序。
private onTenantDataLoadFailed(error: any) {
if (typeof error.error.title != 'undefined') {
this.alertService.stopLoadingMessage();
this.alertService.showStickyMessage("Load Error", `Unable to retrieve tenant data from the server.\r\nErrors: "${Utilities.getHttpResponseMessage(error)}"`,
MessageSeverity.error, error);
this.rows = [];
this.loadingIndicator = false;
this.alertService.showMessage(error.error.title, error.error.status, MessageSeverity.error);
}
}
我已将所有单元测试用例文件放在下面。
describe('Component: TenantEditorComponent', () => {
let component: TenantEditorComponent;
let fixture: ComponentFixture<TenantEditorComponent>;
let submitEl: DebugElement;
let el: HTMLElement;
let scopename: DebugElement;
let scopeObject;
const mockResults = { /* whatever your results should look like ... */ };
const spyTenantService = jasmine.createSpyObj({ getTenants: of(mockResults), });
const spyAlertService = jasmine.createSpyObj({
stopLoadingMessage: null,
showStickyMessage: null,
showMessage: null
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
BrowserAnimationsModule,
HttpClientModule,
RouterTestingModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLanguageLoader
}
}),
NgxDatatableModule,
FormsModule,
UiSwitchModule,
TooltipModule.forRoot(),
ModalModule.forRoot(),
SimpleNotificationsModule.forRoot(),
HttpClientTestingModule
],
declarations: [
TenantEditorComponent,
SearchBoxComponent
],
providers: [
{
provide: LogMessages, useClass: LogMessagesMock
},
HtmlEncoding,
{
provide: Adal5Service, useClass: MockAdal5Service
},
TenantService,
UnitTestStorageOperations, TenantEndpoint,
TenantsEndpointMock,
AlertService,
AppContextService,
EndpointFactory,
NotificationsService,
AppTranslationService,
ConfigurationService,
LocalStoreManager,
{
provide: TenantEndpoint, useClass: TenantsEndpointMock
},
{ provide: TenantService, useValue: spyTenantService }
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TenantEditorComponent);
component = fixture.componentInstance;
});
it('ngOnInit should call onTenantDataLoadFailed() in case of error', () => {
var error = {
error: {
title: 'Tenant already exists',
status: '409'
}
}
spyOn(component, 'onTenantDataLoadFailed').and.callThrough();
debugger;
spyTenantService.getTenants.and.returnValue(ErrorObservable.create({ error }));
fixture.detectChanges();
expect(spyTenantService.getTenants).toHaveBeenCalledTimes(1);
expect(spyAlertService.stopLoadingMessage).toHaveBeenCalled();
expect(component.onTenantDataLoadFailed).toHaveBeenCalled();
expect(spyAlertService.showStickyMessage).toHaveBeenCalled();
expect(spyAlertService.showMessage).toHaveBeenCalled();
});
例如,出于任何原因,API均可归档。在这种情况下,我的错误处理程序将被调用。我想为这种情况编写单元测试用例。有人可以帮我编写负面案例的单元测试用例吗?任何帮助,将不胜感激。谢谢。
答案 0 :(得分:2)
可以在成功(肯定)情况之后立即测试失败(负面)情况。有很多方法可以完成此操作,而到目前为止您还没有提供测试(spec)文件的外观。我将从为服务创建间谍开始,然后将它们添加到TestBed的提供程序中。
另一个关键是在设置成功或失败的spy.returnValue()之前,不要调用夹具.detectChanges(),因此请在it()规范定义中进行此操作。
类似这样的东西:
import { of, throwError } from 'rxjs';
const mockResults = { /* whatever your results should look like ... */ };
const spyTenantService = jasmine.createSpyObj({getTenants: of(mockResults),});
const spyAlertService = jasmine.createSpyObj({
stopLoadingMessage: null,
showStickyMessage: null,
showMessage: null
});
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
imports: [ ],
providers: [
{ provide: TenantService, useValue: spyTenantService },
{ provide: AlertService, useValue: spyAlertService },
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
it('ngOnInit should initialize properly in positive (no error) case', () => {
fixture.detectChanges();
expect(component.results).toEqual(mockResults); // Something like this ...
/* I have no idea what this should look like - you said you have it working */
});
it('ngOnInit should call onTenantDataLoadFailed() in case of error', () => {
spyOn(component, 'onTenantDataLoadFailed').and.callThrough();
spyTenantService.getTenants.and.returnValue(throwError({error: {title: 'defined'}}));
fixture.detectChanges();
expect(spyTenantService.getTenants).toHaveBeenCalledTimes(1);
expect(spyAlertService.stopLoadingMessage).toHaveBeenCalled();
expect(component.onTenantDataLoadFailed).toHaveBeenCalled();
expect(spyAlertService.showStickyMessage).toHaveBeenCalled();
expect(spyAlertService.showMessage).toHaveBeenCalled();
});
更新:
感谢您提供规格文件。正如我在上面的评论中提到的那样,您应该删除您在provider数组中为TenantService和AlertService提供的现有条目,因为您将通过间谍而不是原始服务来提供这些条目。您还忘记了添加以下行:
{ provide: AlertService, useValue: spyAlertService }
因此,提供的提供程序数组应如下所示:
providers: [
{ provide: LogMessages, useClass: LogMessagesMock },
HtmlEncoding,
{ provide: Adal5Service, useClass: MockAdal5Service },
UnitTestStorageOperations,
AppContextService,
EndpointFactory,
NotificationsService,
AppTranslationService,
ConfigurationService,
LocalStoreManager,
{ provide: TenantEndpoint, useClass: TenantsEndpointMock },
{ provide: TenantService, useValue: spyTenantService },
{ provide: AlertService, useValue: spyAlertService }
]
注意:我还从阵列中的较早位置删除了TenantEndpoint和TenantsEndpointMock,因为稍后再指定-您只希望为要注入组件的每个提供程序输入一个条目。但是...我没有看到TenantsEndpointMock的定义,所以我猜想它是在您上面粘贴的代码片段之前声明的,否则也会给您带来错误。 :)
答案 1 :(得分:1)
我认为这应该可以为您提供帮助,如果您有任何问题,请告诉我:
import { async, ComponentFixture, TestBed, fakeAsync, flush } from '@angular/core/testing';
import { ChatPageComponent } from './chat-page.component';
import { FormsModule } from '@angular/forms';
import { UserService } from '../user.service';
import { UserMockService } from '../test/user-mock.service';
import { HubService } from '../hub.service';
import { HubMockService } from '../test/hub-mock.service';
import { CommonHttpService } from '@matrixtools/common';
import { HttpMockService } from '../test/http-mock.service';
describe('ChatPageComponent', () => {
let component: ChatPageComponent;
let fixture: ComponentFixture<ChatPageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ChatPageComponent],
providers: [{ provide: UserService, useClass: UserMockService },
{ provide: HubService, useClass: HubMockService },
{ provide: CommonHttpService, useClass: HttpMockService }],
imports: [FormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChatPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('ping function', () => {
it('should append a green message if hub connects', fakeAsync(() => {
// arrange
spyOn(component.hubConnection, 'invoke').and.returnValue(Promise.resolve('good promise'));
let expectedColor = 'green';
component.messages = [];
// act
component.ping();
flush();
// assert
let actualColor = component.messages[1].color;
expect(actualColor).toBe(expectedColor);
}));
it('should append a red message if hub connection fails', fakeAsync(() => {
// arrange
spyOn(component.hubConnection, 'invoke').and.returnValue(Promise.reject('bad promise'));
let expectedColor = 'red';
component.messages = [];
// act
component.ping();
flush();
// assert
let actualColor = component.messages[1].color;
expect(actualColor).toBe(expectedColor);
}));
});
});