簡體   English   中英

如何編寫角度5的api失敗的單元測試用例?

[英]How to write unit test case for api failure in angular 5?

嗨,我正在為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均可歸檔。 在這種情況下,我的錯誤處理程序將被調用。 我想為這種情況編寫單元測試用例。 有人可以幫我編寫負面案例的單元測試用例嗎? 任何幫助,將不勝感激。 謝謝。

可以在成功(積極)的情況之后立即測試失敗(負面)的情況。 有很多方法可以完成此操作,而到目前為止您還沒有提供測試(spec)文件的外觀。 我將從為服務創建間諜開始,然后將它們添加到TestBed的提供程序中。

另一個關鍵是在設置成功或失敗的spy.returnValue()之前,不要調用Fixture.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數組應如下所示:

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的定義,所以我猜想它是在您上面粘貼的代碼片段之前聲明的,否則也會給您帶來錯誤。 :)

我認為這應該可以為您提供幫助,如果您有任何問題,請告訴我:

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);
    }));
  });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM