【问题标题】:how to test a function with condition in ngOnInit如何在 ngOnInit 中使用条件测试函数
【发布时间】:2019-08-29 15:49:02
【问题描述】:

我想用来自 ngOnInit 中的服务的条件来测试一个函数。我尝试了很多方法,但没有成功。我有各种各样的错误。

我的组件

export class MainSectionComponent implements OnInit {    

  propertiesFrDb: PropertyPost[];

  constructor(
    private getPropertiesFrDbService: GetPropertiesFrDbService,
    private propertyWarehouseService: PropertyWarehouseService,
    private router: Router,
    config: NgbCarouselConfig,
    private userService: UserService,
    private sharedFunctionService: SharedFunctionService,
    private returnResponseAfterUserLoginService: ReturnResponseAfterUserLoginService,
    private localStorageService: LocalStorageServiceService,
    private dialogLoginService: DialogLoginService,
    @Inject(PLATFORM_ID) private platformId: Object
  ) { 
    // this.isBrowser = isPlatformBrowser(platformIds);

  }

  ngOnInit() {
    this.getPropertiesFrDb();

  }

  getPropertiesFrDb() {
    if (this.propertyWarehouseService.currentValuesProperties) {
      this.propertyWarehouseService.getPropertyHome$.subscribe(
        prop => {
          console.log(prop);

         return this.propertiesFrDb = prop
        }
      )
    } else {

      this.getPropertiesFrDbService.getHomeProperties()
        .subscribe(property => {
          // console.log(property['results']);
          this.propertyWarehouseService.setPropertiesHome(property['results'])
         return   this.propertiesFrDb = property['results']

        },

        )
    }
  }

我想在ngOnInit 中测试this.getPropertiesFrDb() 我想用this.propertyWarehouseService.currentValuesProperties !== ''测试这个案例并检查this.getPropertiesFrDbService.getHomeProperties()是否被调用并检查propertiesFrDb的值

还有我的 spec.ts 文件

import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';

import { MainSectionComponent } from './home-properties.component';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { MaterialModule } from 'src/app/material/material.module';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { GetPropertiesFrDbService } from 'src/app/services/getPropertiesFromDb/get-properties-fr-db.service';
import { MOCKPROPERTIES, MockPropertyWarehouseService } from 'src/app/mocks/property-post';
import { NgxPaginationModule, PaginatePipe } from 'ngx-pagination';
import { PropertyWarehouseService } from 'src/app/services/propertyWarehouse/property-warehouse.service';
import { BsDropdownModule } from 'ngx-bootstrap';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { StorageServiceModule } from 'angular-webstorage-service';
import { of } from 'rxjs/internal/observable/of';

fdescribe('MainSectionComponent', () => {
  let component: MainSectionComponent;
  let fixture: ComponentFixture<MainSectionComponent>;
  const PROPERTYMODEL = MOCKPROPERTIES;
  const spyPropertyWarehouseService = jasmine.createSpyObj('spypropertyWarehouseService', ['currentValuesProperties', 'getPropertyHome$']);


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        MaterialModule,
        HttpClientTestingModule,
        RouterTestingModule.withRoutes([]),
        NgxPaginationModule,
        BsDropdownModule.forRoot(),
        NgbModule,
        StorageServiceModule,


      ],
      declarations: [
        MainSectionComponent,

      ],
      providers: [
        {
          provide: PropertyWarehouseService,
          useValue:  spyPropertyWarehouseService
      }

      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],

    })
      .compileComponents();

  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MainSectionComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  });


  it('should create', (() => {
    // console.log('properties', component);
    expect(component).toBeTruthy();
  }));

  it('Should get  propertiesFrDb from GetPropertiesFrDbService', async(() => {
    spyPropertyWarehouseService.currentValuesProperties.and.returnValue(PROPERTYMODEL);
    spyPropertyWarehouseService.getPropertyHome$.and.returnValue(of(PROPERTYMODEL));
    expect(component.propertiesFrDb).toBe(PROPERTYMODEL);

    console.log('spy',spyPropertyWarehouseService);

  }));

});

【问题讨论】:

  • spec 文件上方运行时遇到什么错误?
  • 另外,returngetHomeProperties().subscribe() 里面做什么?
  • 失败:spyPropertyWarehouseService.getPropertyHome$.subscribe 不是函数
  • 如果我的回答对你有用,请告诉我

标签: javascript angular typescript karma-jasmine angular8


【解决方案1】:

尝试如下创建存根:

export class PropertyWarehouseServiceStub{
   currentValuesProperties = '';
   getPropertyHome$ = new BaheviorSubject<any>('someObj');
   setPropertiesHome(){  }

}

export class GetPropertiesFrDbServiceStub{
   getHomeProperties(){
     return of({results: 'val'})
   }
}

component 文件中将服务公开在构造函数中,以便我们可以覆盖它的一些行为:

constructor(...,
   public propertyWarehouseService: PropertyWarehouseService, 
   public getPropertiesFrDbService: GetPropertiesFrDbService,
   ....)

spec 文件中为:

      providers: [
        {
          provide: PropertyWarehouseService,
          useClass:  PropertyWarehouseServiceStub
        },{
          provide: GetPropertiesFrDbService,
          useClass:  GetPropertiesFrDbServiceStub
        }
      ],

......
....
..
it('should call getPropertiesFrDb() in ngOnInit',()=>{
     spyOn(component,'getPropertiesFrDb').and.callThrough();
     component.ngOnInit();
     expect(component.getPropertiesFrDb).toHaveBeenCalled();
})

it('inside getPropertiesFrDb() should call getPropertiesFrDbService.getHomeProperties() when "propertyWarehouseService.currentValuesProperties" is empty,()=>{
  spyOn(component.getPropertiesFrDbService,'getHomeProperties').and.callThrough();
  spyOn(component.propertyWarehouseService,'setPropertiesHome').and.callThrough();
  component.getPropertiesFrDb();
  expect(component.getPropertiesFrDbService.getHomeProperties).toHaveBeenCalled();
  expect(component.propertyWarehouseService.setPropertiesHome).toHaveBeenCalledWith('val');
  expect(component.propertiesFrDb).toBe('someObj'); 
})

it('inside getPropertiesFrDb() should not call getPropertiesFrDbService.getHomeProperties() when "propertyWarehouseService.currentValuesProperties" is NOT empty,()=>{
  component.propertyWarehouseService.currentValuesProperties = 'Not empty';
  spyOn(component.getPropertiesFrDbService,'getHomeProperties').and.callThrough();
  spyOn(component.propertyWarehouseService,'setPropertiesHome').and.callThrough();
  component.getPropertiesFrDb();
  expect(component.getPropertiesFrDbService.getHomeProperties).not.toHaveBeenCalled();
  expect(component.propertyWarehouseService.setPropertiesHome).not.toHaveBeenCalledWith('val');
  expect(component.propertiesFrDb).toBe('val');
})

您可以参考this intro article written by me on Karma-jasmine,其中包含多个测试用例的更多文章参考。

This one is very much similar to what you are looking for.我打算再写一些文章,以防你想关注。


另外,我不知道您为什么在getPropertiesFrDb() 中使用return,如下面的getPropertiesFrDb()

return this.propertiesFrDb = prop

这是没有用的,因为该函数的值尚未分配给ngOnInit 中的任何变量。

【讨论】:

  • @user9714967:太棒了!希望文章对你也有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2021-10-15
  • 2016-08-09
  • 2017-07-28
  • 2018-06-13
  • 2017-11-20
  • 2020-01-30
相关资源
最近更新 更多