角度单元测试组合最新 [英] Angular unit test combineLatest

查看:12
本文介绍了角度单元测试组合最新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从使用ANGLE中的Jest框架进行单元测试开始有一段时间了。然而,我陷入了需要对comineLatestRxJS操作符进行单元测试的情况。我的组件如下所示。

组件:

public userData;
public productData;

constructor(
    private readonly userService: UserService,
    private readonly productService: ProductService
) {}

public ngOnInit() {
    this.initialize();
}

public initialize() {
    combineLatest([
        this.userService.getUserData(),
        this.productService.getProductData()
    ])
    .subscribe([userData, productData] => {
        this.userData = userData;
        this.productData = productData;
    });
}

我模拟了我的服务和单元测试,如下所示。

it('should initialize user and product data', fakeAsync(() => {
    spyOn(userService, 'getUserData');
    spyOn(productService, 'getProductData');
    component.initialize();
    tick();
    fixture.detectChanges();
    expect(userService.getUserData).toHaveBeenCalled();
    expect(productService.getProductData).toHaveBeenCalled();
    expect(component.userData).toBeDefined();
    expect(component.productData).toBeDefined();
}));

此测试失败,已接收:未定义。但相同类型的测试在处理单个可观察对象时可用。

推荐答案

我将尝试用不同的方法回答该问题。

让我们看看您的代码,测试简单的代码块比测试长代码更容易。

将变量分配给您的属性会容易得多。这样,您就可以简单地测试属性

见下面改进的代码;

constructor(
    private readonly userService: UserService,
    private readonly productService: ProductService
) {}
userData: any;
productData: any;
userData$ = this.userService.getUserData().pipe(
  tap(userData => this.userData = userData)
);
productData$ = this.productService.getProductData().pipe(
  tap(productData = productData => this.productData = productData)
)

v$ = combineLatest([this.userData$, this.productData$]).pipe(
  map(([userData, productData]) => ({ userData, productData }))
)
initialize() {
  v$.subscribe()
}
ngOnInit() {
    this.initialize();
}

返回初始测试

现在,让我们尝试测试您的初始代码,并了解为什么测试不起作用。 来自官方documentation

当任何可观察对象发出一个值时,从每个

让我们来看看下面的代码

    spyOn(userService, 'getUserData');
    spyOn(productService, 'getProductData');

上述代码是否发出任何值?答案是否定的,因此代码this.userService.getUserData()this.productService.getProductData()不会返回任何值,因此不会发出任何值。combineLatest因此不会发出任何值。

解决方案

您需要从spyOn()函数返回Observable,如下所示 SpyOn(userService,‘getUserData’).and.returValue(共({}));

现在,可观察对象将发出,测试将通过

更好代码的最终建议。

您可以考虑使用async管道来处理您的订阅。使用async管道可以将代码编写如下

constructor(
    private readonly userService: UserService,
    private readonly productService: ProductService
) {}
userData$ = this.userService.getUserData()
productData$ = this.productService.getProductData()
v$ = combineLatest([this.userData$, this.productData$]).pipe(
  map(([userData, productData]) => ({ userData, productData }))
)

在您的html中

<ng-container *ngIf='v$ | async'>
  {{ v.userData | json }}
  {{ v.productData| json }}   
</ng-container>

在您的测试文件中可以

it('should initialize user and product data', fakeAsync(() => {
    spyOn(userService, 'getUserData').and.returnValue(of({}));
    spyOn(productService, 'getProductData').and.returnValue(of({}));
    tick();
    fixture.detectChanges();
    component.v$.subscribe({
      next: (v) => {
        expect(v.userData).toBeDefined();
        expect(v.productData).toBeDefined();
      }
    })
}));

上述测试只是检查如果我们订阅v$,则userDataproductData被定义

这篇关于角度单元测试组合最新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆