8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何使用 Jest+jest-auto-spies 监视公共领域

joseville 3月前

98 0

我有这个试图模拟的 Angular 服务:@Injectable({ providedIn: 'root',})export class NotificationsService { private _notifications = new Subject (); 民众

我正在尝试模拟这个 Angular 服务:

@Injectable({
  providedIn: 'root',
})
export class NotificationsService {
  private _notifications = new Subject<Notification>();
  public notifications: Observable<Notification> = this._notifications.asObservable();
  public crudNotifications: Observable<CrudNotification> = this._notifications.asObservable().pipe(
    filter(notification => notification.notificationType === 'crud-notification'),
    map(notification => notification as CrudNotification)
  );
//....
}

我刚刚将其迁移到 Jest,并试图弄清楚当我的测试服务尝试访问时如何模拟返回自定义可观察对象 NotificationsService.crudNotifications

目前,我有这个:

describe('OrganizationUsersService', () => {
  let organizationUsersService: OrganizationUsersService;
  let crudNotifications!: Subject<CrudNotification>;
  let notificationServiceMock!: Spy<NotificationsService>
  let storeMock!: Spy<Store>;
  let httpTestingController! :HttpTestingController;
  
  beforeEach(()=>{
    

    TestBed.configureTestingModule({
      providers:[
      {provide: NotificationsService, useValue: createSpyFromClass(NotificationsService)},
      {provide: Store, useValue:     createSpyFromClass(Store)  },
      {provide: Router, useValue:     createSpyFromClass(Router)  },
      provideHttpClient(),
      provideHttpClientTesting(),
      ]
    })
    httpTestingController = TestBed.inject(HttpTestingController);
    notificationServiceMock = TestBed.inject<any>(NotificationsService);
    storeMock = TestBed.inject<any>(Store);

    //Common mocked stuff behavior for every methods here    
    crudNotifications = new Subject<CrudNotification>();
    notificationServiceMock.crudNotifications = crudNotifications.asObservable();

    storeMock.dispatch.mockReturnValue(of());
    storeMock.select.mockReturnValue(of({ id: 'some-id' }));

    //Finally create the service to test:    
    organizationUsersService = TestBed.inject(OrganizationUsersService);
  })

    fit('should refresh the store when the backend inform a new role attribution has been added for the current organization id', fakeAsync(() => {
    //Arrange
    organizationUsersService.initialize(); //Required to register

    //Act
    crudNotifications.next({
      dataType: 'organization.role-attribution',
      operationType: 'add',
      id: 'some-id',
      notificationType: 'crud-notification',
    });
    tick();

    //Assert
    httpTestingController.expectOne(environment.backendUrl + 'some/stuff').flush({});
    httpTestingController.expectOne(environment.backendUrl + 'some/other/stuff').flush({});

    expect(storeMock.dispatch).toHaveBeenCalledWith(expect.any(SetLoadingAction));
    organizationUsersService.dispose();
  }));
}));

这不起作用,因为我尝试设置的可观察对象没有启用 Spy 方法。我尝试过这个:

notificationServiceMock.crudNotifications.mockReturnValue(crudNotifications);

但公共字段上不存在 mockReturnValue 方法。

有没有办法在公共领域模拟价值?

帖子版权声明 1、本帖标题:如何使用 Jest+jest-auto-spies 监视公共领域
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由joseville在本站《angular》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我无法理解在这种情况下如何使用 async/await。我有一个函数 GetAdditionalProducts(),它调用一个服务并返回一个结果。我在其他地方调用该函数...

    我无法理解在这种情况下如何使用 async/await。我有一个函数 GetAdditionalProducts() ,它调用一个服务并返回一个结果。我在需要访问该结果的其他地方调用了该函数,但它在响应可用之前执行了该代码。我如何使用 async/await 等待响应然后再继续?

      onSearch() {
        this.GetAdditionalProducts();
        //other stuff that requires the response from above function
      }   
    
      GetAdditionalProducts() {
        this.proposalService.getProductList(this.filter).subscribe(response => {
          this.additionalProducts = response.productList;
        });
      }
    
  • 将 angular 版本从 11 升级到 17.3.8 后,无论在 @NgModule 中使用入口组件,我的代码中都会抛出错误行。因此,运行时所有 npm 模块都会抛出错误...

    将 angular 版本从 11 升级到 17.3.8 后,我的代码中无论在 @NgModule 中使用入口组件的地方都会抛出错误行。因此,在本地运行它时,它会在所有 npm 模块中抛出错误。

    import { NgModule } from '@angular/core';
    import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
    import { CommonModule } from '@angular/common';
    import { Ng2SmartTableModule } from 'ng2-smart-table';
    import { ThemeModule } from '../../@theme/theme.module';
    import { FormsModule } from '@angular/forms';
    import { UsersComponent } from './users.component';
    import { NbCardModule, NbButtonModule, NbSelectModule, NbInputModule, NbSpinnerModule } from '@nebular/theme';
    import { AddUserComponent } from './add-user/add-user.component';
    import { EditUserComponent } from './edit-user/edit-user.component';
    import { DeleteUserComponent } from './delete-user/delete-user.component';
    
    const COMPONENTS = [
      UsersComponent,
      AddUserComponent,
      EditUserComponent,
      DeleteUserComponent,
    ];
    
    const ENTRY_COMPONENTS = [
      AddUserComponent,
      EditUserComponent,
      DeleteUserComponent,
    ];
    
    const MODULES = [
      CommonModule,
      ThemeModule,
      NgbModule,
      NbButtonModule,
      NbSelectModule,
      NbInputModule,
      NbCardModule,
      Ng2SmartTableModule,
      FormsModule,
      NbSpinnerModule
    ];
    
    @NgModule({
      imports: [...MODULES],
      declarations: [...COMPONENTS,],
      entryComponents: [...ENTRY_COMPONENTS]
    })
    export class UsersModule { }
    
  • @BojanKogoj 谢谢你指出这一点。我已将我的答案修改为使用 lastValueFrom 而不是 toPromise。

  • 我这样做了,因为原始代码中没有处理它。我可以添加错误处理,但我制作的示例不应该按原样使用,而是用来演示如何自己实现承诺。

  • toPromise 仍然比自己使用 new Promise 更好。请注意,您忘记处理错误了。

  • 我看到您使用了 \'subscribe\',这意味着 RxJS。您可以使用 lastValueFrom 函数将您的可观察对象转换为承诺。

    import { lastValueFrom } from 'rxjs'
    
    async GetAdditionalProducts() {
        return lastValueFrom(this.proposalService.getProductList(this.filter))
    }
    

    如果您想自己实现,您可以将您的 this.proposalService.getProductList(this.filter) 调用包装成一个承诺,然后在您的“订阅”回调中解决该承诺。

    您传递给 Promise 的任何内容都 resolve 将成为您的承诺的返回值,并且在使用 await 函数时可以访问。

     async GetAdditionalProducts() {
        return new Promise(resolve => {
          this.proposalService.getProductList(this.filter).subscribe(response => {
            resolve(response.productList);
          });
        })
      }
    
    

    然后,您可以致电 GetAdditionalProducts 并等待回复。

    async onSearch() {
      this.additionalProducts = await this.GetAdditionalProducts();
    }
    

    编辑:将可观察对象转换为承诺的新标准似乎是 lastValueFrom 。我已编辑了我的答案。感谢 Bojan 指出这一点。

  • 当您考虑可观察对象时,请考虑将其他操作放在订阅中是正常的。订阅中的代码是异步的(等待 API 完成),而订阅下方的代码是同步的(不等待完成),因此您需要将代码移到里面以链接操作。

    当使用可观察对象转换为承诺并返回时似乎需要额外的努力,并且只有在绝对需要时才应该这样做。

      onSearch() {
        this.GetAdditionalProducts();
      }   
    
      GetAdditionalProducts() {
        this.proposalService.getProductList(this.filter).subscribe(response => {
          this.additionalProducts = response.productList;
          this.additionalActions();
        });
      }
    
      additionalActions() {
        //other stuff that requires the response from above function
      }
    
  • 在 Angular 中,你几乎从来不用使用 async/await。有什么理由要用吗?

  • TypeScript 不提供“服务”。您指的是 Angular 服务和 HTTP 调用吗?

  • mapf 3月前 0 只看Ta
    引用 11

    entryComponents 对于更高版本的角度来说,不再需要。

    从所有模块中 entryComponents 删除

    将这些组件移至声明数组即可。如果您收到任何错误

    Error: src/app/pages/web-filter/categories/categories.component.html:4:7 - error NG8001: 'nb-card-header' is not a known element:
    1. If 'nb-card-header' is an Angular component, then verify that it is part of this module.
    2. If 'nb-card-header' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    
    4 <nb-card-header>
    

    您必须将相应的模块/组件导入到您声明它的模块中,直到不再出现错误。

返回
作者最近主题: