typescript 嵌套服务的模拟服务返回未定义

9bfwbjaz  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(157)

我目前正在处理一个Angular项目,并且正在使用Karma + Jasmine为一个组件创建单元测试,因此我有一个HTML,其中包含一个ngIf,调用API服务如下:

    • 超文本标记语言**
<div class="row" *ngIf="apiService.utilsService.userBelongsTo('operations')"></div">

*ngIf中的服务就是我想要在下面的spec.ts上模拟的服务

    • 技术支助**
export class CashFlowSalariesComponent implements OnInit, OnChanges {
constructor(
public apiService: ApiService,
) {}
    • SPECT. TS**
describe('CashFlowSalariesComponent', () => {
      let fixture: ComponentFixture < CashFlowSalariesComponent > ;
      let mockApiService;
      let data;

      beforeEach(async(() => {
        data = [{
          id: 1006,
          role: "Developer",
          ...
        }]

        mockApiService = jasmine.createSpyObj(['userBelongsTo'])

        TestBed.configureTestingModule({
          schemas: [CUSTOM_ELEMENTS_SCHEMA],
          imports: [
            RouterTestingModule,
            FormsModule,
            ReactiveFormsModule,
            BrowserModule,
            HttpClientTestingModule,
            ToastrModule.forRoot({
              positionClass: 'toast-bottom-right'
            })
          ],
          declarations: [
            CashFlowSalariesComponent,
          ],
          providers: [{
              provide: ApiService,
              useValue: mockApiService
            }, UserService, ProfileService, VettingStatusService, ApplicationRoleService,
            SeniorityLevelService, PlacementStatusService, EducationLevelService, UtilsService, ShirtSizeService,
            CountryService, CityService, PostalCodeService, StateService, ClientSectorService, JobService, ProfileActivityService, ProfileSalaryActivityService, ClientService, RequestTimeOffService, TimeOffTypeService, PulsecheckDetailService, PulsecheckMasterService,
            PulsecheckQuestionService, ExpenseService, DepartmentService, ExchangeRateService, SkillCategoriesService, ProfileRoleService,
            ToastrService
          ]

        })

        fixture = TestBed.createComponent(CashFlowSalariesComponent);
      }));

      it('should set salaries data correctly', () => {
        mockApiService.userBelongsTo.and.returnValue(of('operations'))
        debugger;
        fixture.detectChanges();
      })

如您所见,我尝试创建API服务的模拟:mockApiService = jasmine.createSpyObj(['userBelongsTo']),则在it中使用:mockApiService.userBelongsTo.and.returnValue(of('operations')),但是当我调试它时,它抛出如下图所示的未知

测试返回以下错误:
无法读取未定义的属性(读取"userBelongsTo")
我不知道发生这种情况是否是因为userBelongs属于apiService中的另一个服务:

    • Api服务**
@Injectable()
export class ApiService {
 public utilsService: UtilsService;

constructor(private injector: Injector) {
this.utilsService = injector.get(UtilsService);
}
}
    • 实用程序服务:**
userBelongsTo(groupName: string) {
    return this.groups.split(',').reduce((c, g) => c || g.toUpperCase() == groupName.toUpperCase(), false);
  }

我怎样才能让这个工作?

2hh7jdfx

2hh7jdfx1#

依赖注入应该是private,为什么模板HTML要处理服务调用,不要把服务调用委托给模板,在组件中做一个合适的函数,这样模板会更干净

<div class="row" *ngIf="getBelongsTo()"></div">
constructor(private apiService: ApiService) {}

getBelongsTo(): boolean {
  // I guess userBelongsTo returns either a string or undefined,
  // so using !! creates a valid boolean
  // if userBelongsTo returns a valid string, returns TRUE
  // if returns undefined/null returns FALSE
  return !!this.apiService.utilsService.userBelongsTo('operations');
}

为了进行测试,您需要在**开始测试之前提供userBelongsTo**中的mock/fake值。另外,您模拟服务的方式是错误的,可能如下所示:

const mockApiService = jasmine.createSpyObj<ApiService>('ApiService', ['userBelongsTo']);
let data;

beforeEach(() => {
  data = [{ id: 1006, role: "Developer", ...}];
  mockApiService.userBelongsTo.and.returnValue(of('operations'));
}

beforeEach(async() => {
  TestBed.configureTestingModule({
    declarations: [...],
    provides: [{provide: ApiService, useValue: mockApiService}]
  })
})

我不知道发生这种情况是否是因为userBelongs属于apiService内的另一个服务
当单元测试时,你不关心当被注入到组件中时任何依赖关系是如何实现的,你只是在模拟所有的依赖关系,所以这无关紧要。
需要注意的一点是,既然您提供了ApiService的实现方式,请记住,在某些module中,需要将ApiService添加到providers数组中,因为它不是作为root提供的,例如x:@Injectable({ provideIn: 'root' })

相关问题