代码之家  ›  专栏  ›  技术社区  ›  dman

在Angular单元测试中似乎无法模拟行为主体

  •  -1
  • dman  · 技术社区  · 10 月前

    使用Angular 16和Jasmine/Karma。

    我订阅了一个名为的行为主题 tableList$

    
        ngOnInit() {                                                   
          const { pageNumber } = this.subscribersService.getMiscValues();
          this.subscribersService.initPage(pageNumber);
    >>    this.subscribersService.tableList$.subscribe((tableList) => {
            //  this.tableList = this.deleteSubscribersService.setDeleteCheckboxStates(tableList);                    
          });                                                                                
        } 
    

    我试图嘲笑行为主体,但我越来越 this.subscribersService.tableList$.subscribe is not a function .

    你知道我做错了什么吗?

    注意,我也试过 subscribersServiceMock.tableList$.and.returnValue({ subscribe: () => tableListMock$.subscribe }); 没有成功

    fdescribe('ManageSubscribersComponent', () => {
      let component: ManageSubscribersComponent;
      let fixture: ComponentFixture<ManageSubscribersComponent>;
      let miscMockValues;
      let tableMockData;
      let tableListMock$;
      let dialogServiceMock
      let dialogSubjectMock;
      let subscribersServiceMock;
      let deleteSubscribersServiceMock;
    
      const displayedColumns = [
        'id',
        'name',
        'description',
        'createdBy',
        'createdOn',
        'updatedBy',
        'updatedOn',
      ];
    
      beforeEach(() => {
        tableListMock$ = new Subject();
        dialogSubjectMock = new Subject();
    
        dialogServiceMock = jasmine.createSpyObj([
          'open',
          'afterClosed',
        ]);
    
        deleteSubscribersServiceMock = jasmine.createSpyObj([
          'deleteSubscribers',
        ]);
    
    
        subscribersServiceMock = jasmine.createSpyObj([
          'resetMiscValues',
          'getMiscValues',
          'initPage',
          'tableList$',
        ]);
    
        miscMockValues = {
          pageNumber: 1,
          pageSize: 25,
          sort: '',
          active: true,
          testMode: false,
          searchTerms: '',
        };
    
    
        subscribersServiceMock.getMiscValues.and.returnValue(miscMockValues);
        subscribersServiceMock.tableList$.and.returnValue(tableListMock$);
        dialogServiceMock.afterClosed.and.returnValue(dialogSubjectMock);
    
        TestBed.configureTestingModule({
          declarations: [ManageSubscribersComponent],
          imports: [
            HttpClientTestingModule,
            MatFormFieldModule,
            MatIconModule,
            MatSliderModule,
            MatTableModule,
            MatFormFieldModule,
            MatInputModule,
            BrowserAnimationsModule,
            MatPaginatorModule,
            MatDialogModule,
          ],
          schemas: [
            CUSTOM_ELEMENTS_SCHEMA,
            NO_ERRORS_SCHEMA,
          ],
          providers: [
            {
              provide: SubscribersService,
              useValue: subscribersServiceMock,
            },
            {
              provide: DeleteSubscribersService,
              useValue: deleteSubscribersServiceMock,
            },
          ],
        });
    
        fixture = TestBed.createComponent(ManageSubscribersComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    
    
      fit('should init', fakeAsync(() => {
        fixture.whenStable().then(() => {
          expect(component.displayedColumns).toEqual(displayedColumns);
          expect(subscribersServiceMock.getMiscValues).toHaveBeenCalled();
        })
      }));
    
    1 回复  |  直到 10 月前
        1
  •  2
  •   davidlj95    10 月前

    正如评论中所述,问题在于测试设置

    设置时 SubscribersService 模仿做

    subscribersServiceMock = jasmine.createSpyObj([
          'resetMiscValues',
          'getMiscValues',
          'initPage',
          'tableList$',
        ]);
    

    数组中的这些名称将是 方法 根据 createSpyObj docs

    然而, 订阅服务 使用 tableList$ 作为一种财产。因为它确实如此 this.tableList$ 因为它是一种可观察的对象,并且不像使用方法那样调用它: this.tableList$() .

    如果你想用你的 tableListMock 主题为 表列表$ 财产 ,您可以使用下一个可选参数 createSpyObj :

    subscribersServiceMock = jasmine.createSpyObj([
          'resetMiscValues',
          'getMiscValues',
          'initPage',
        ], { tableList$: tableListMock$ });
    

    As createSpyObj docs 状态,最后一个参数可以定义创建间谍的属性。或者一个对象,用它们在对象中的值来实际定义属性。

    您还可以传递一个方法名数组:

    subscribersServiceMock = jasmine.createSpyObj([
          'resetMiscValues',
          'getMiscValues',
          'initPage',
          'tableList$',
        ], ['tableList$']);
    

    然后, spies will be created for the property accessor 这样你就可以在什么时候监视 表列表$ get set .

    以下是如何配置 得到 间谍,这样 subscribersServiceMock.tableList$ 返回模拟主题:

    subscribersServiceMock = jasmine.createSpyObj(
     [
       // method names as ususal
     ], 
     ['tableList$']
    );
    const tableList$GetterSpy = Object.getOwnPropertyDescriptor(
      subscribersServiceMock,
      'tableList$',
    )!.get as jasmine.Spy
    tableList$GetterSpy.and.returnValue(mockTableList$)
    

    如果你只想设置值,有点麻烦,之前传递对象的方式更短。通过这种方式,您可以验证 表列表$ 通过使用间谍访问:

    expect(tableList$Getter).toHaveBeenCalled()