如何在角度中对取消订阅功能进行单元测试

2024-04-16

我想找到一种方法来测试订阅和主题上的取消订阅函数调用。

我想出了一些可能的解决方案,但每一种都有优点和缺点。请记住,我不想出于测试目的而更改变量的访问修饰符。

  1. 通过反射访问组件的私有变量。

在这种情况下,我有一个存储订阅的私有类变量:

组件.ts:

private mySubscription: Subscription;
//...
ngOnInit(): void {
    this.mySubscription = this.store
        .select(mySelector)
        .subscribe((value: any) => console.log(value));
}

ngOnDestroy(): void {
    this.mySubscription.unsubscribe();
}

组件规格:

spyOn(component['mySubscription'], 'unsubscribe');
component.ngOnDestroy();
expect(component['mySubscription'].unsubscribe).toHaveBeenCalledTimes(1);

pros:

  • 我可以到达我的订阅。
  • 我可以测试取消订阅方法是在右侧调用的 订阅。

cons:

  • 我只能通过反思才能达到我的订阅,如果可能的话我想避免这种情况。

  1. 我创建了一个用于订阅的变量,就像选项 1 中一样,但我没有通过反射访问该变量,而是简单地检查取消订阅方法是否已被调用,而不知道来源。

组件.ts:与选项 1 相同


组件规格:

spyOn(Subscription.prototype, 'unsubscribe');
component.ngOnDestroy();
expect(Subscription.prototype.unsubscribe).toHaveBeenCalledTimes(1);

pros:

  • 我可以测试取消订阅方法被调用

cons:

  • 我无法测试调用的取消订阅方法的来源。

  1. 我实现了一个辅助函数,它对传递的订阅参数调用取消订阅方法。

订阅.helper.ts:

export class SubscriptionHelper {

    static unsubscribeAll(...subscriptions: Subscription[]) {
        subscriptions.forEach((subscription: Subscription) => {
                subscription.unsubscribe();
            });
    }
}

组件.ts:与选项 1 相同,但 ngOnDestroy 不同:

ngOnDestroy(): void {
    SubscriptionHelper.unsubscribeAll(this.mySubscription);
}

组件规格:

spyOn(SubscriptionHelper, 'unsubscribeAll');
component.ngOnDestroy();
expect(SubscriptionHelper.unsubscribeAll).toHaveBeenCalledTimes(1);

pros:

  • 我可以测试辅助函数是否被调用

cons:

  • 我无法测试是否在特定订阅上调用了取消订阅函数。

你们有什么建议?如何在单元测试中测试清理工作?


我遇到了完全相同的问题,这是我的解决方案:

组件.ts:

private subscription: Subscription;
//...
ngOnInit(): void {
    this.subscription = this.route.paramMap.subscribe((paramMap: ParamMap) => {
        // ...
    });
}

ngOnDestroy(): void {
    this.subscription.unsubscribe();
}

组件规格:


let dataMock;

let storeMock: Store;
let storeStub: {
    select: Function,
    dispatch: Function
};

let paramMapMock: ParamMap;
let paramMapSubscription: Subscription;
let paramMapObservable: Observable<ParamMap>;

let activatedRouteMock: ActivatedRoute;
let activatedRouteStub: {
    paramMap: Observable<ParamMap>;
};

beforeEach(async(() => {
    dataMock = { /* some test data */ };

    storeStub = {
        select: (fn: Function) => of((id: string) => dataMock),
        dispatch: jasmine.createSpy('dispatch')
    };

    paramMapMock = {
        keys: [],
        has: jasmine.createSpy('has'),
        get: jasmine.createSpy('get'),
        getAll: jasmine.createSpy('getAll')
    };

    paramMapSubscription = new Subscription();
    paramMapObservable = new Observable<ParamMap>();

    spyOn(paramMapSubscription, 'unsubscribe').and.callThrough();
    spyOn(paramMapObservable, 'subscribe').and.callFake((fn: Function): Subscription => {
        fn(paramMapMock);
        return paramMapSubscription;
    });

    activatedRouteStub = {
        paramMap: paramMapObservable
    };

    TestBed.configureTestingModule({
       // ...
       providers: [
           { provide: Store, useValue: storeStub },
           { provide: ActivatedRoute, useValue: activatedRouteStub }
       ]
    })
    .compileComponents();
}));

// ...

it('unsubscribes when destoryed', () => {
    fixture.detectChanges();

    component.ngOnDestroy();

    expect(paramMapSubscription.unsubscribe).toHaveBeenCalled();
});

这对我有用,我希望对你也有用!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在角度中对取消订阅功能进行单元测试 的相关文章

随机推荐

  • Android:如何禁用 FEATURE_NO_TITLE

    我希望我的 Android 应用程序的行为如下 1 纵向模式 带标题栏 2 横向模式 无标题栏 因为高度限制 我知道我可以实现 1 使用 requestWindowFeature Window FEATURE NO TITLE 但是 当我旋
  • 正则表达式:如何排除多个字符组?

    我有一组网址 产品 类别 顾客 现在假设客户名为 john 我想帮助 john 使用较短的 url 访问他自己的帐户页面 before customers john after john 假设客户名称是唯一的 我正在尝试找出一个合适的正则表
  • DDD 领域模型复杂验证

    我正在努力使用域驱动设计原则重写我的 ASP NET MVC 应用程序 我正在尝试验证我的用户实体 到目前为止 我能够验证基本规则 例如用户名和密码是非空 空白字符串 然而规则之一是 我需要确保用户名是唯一的 但是 我需要访问数据库才能执行
  • 当 AVQueuePlayer 完成最后一个播放器项目时如何执行某些操作

    我有一个 AVQueuePlayer 它是由 4 个 AVPlayerItems 组成的数组创建的 并且一切都运行良好 当队列中的最后一项完成播放时 我想做点什么 我在这里查看了很多答案 这是看起来最有希望实现我想要的答案 声音播放完毕后执
  • Scala 泛型 - 为什么我无法在泛型类中创建参数化对象?

    我目前正在学习scala 为什么此代码不起作用 class GenClass T var d T var elems List T Nil def dosom x T var y new T y 我得到 错误 需要类类型 但找到了 T 代替
  • 如何使用 aws API Gateway 从另一个模型引用一个模型

    假设我有一个模型 Pet type object properties name type integer age type integer 还有另一个模型 Human type object properties name type in
  • 求数组中和的快速算法

    我正在寻找一种快速算法 我有一个大小为 n 的 int 数组 目标是找到数组中的所有模式x1 x2 x3 are different elements in the array such that x1 x2 x3 例如我知道有一个大小为
  • 在其事件处理程序中删除 FMX 对象

    我有以下组件 tncrdragdata tframedscrollbox tdragdata tgroupbox 主要思想是将它们组合起来并将它们用作列表框 我需要这样 该组框包含五个tedit 一个 tcombobox 和一个tbutto
  • 是否可以使用 Delphi 将 XML 发送和接收到 WSDL 函数?

    我们过去曾在 Delphi 中使用 Web 服务 这些服务很简单 参数很少 并向客户端返回单个值 我们工作的新服务应该能够输入 XML 并接收 XML 输出 有没有可以用于此目的的组件 当我尝试使用如下所示的方法时 出现错误 SearchA
  • 将对象传递给新表单

    我想做这样的事情 主要表格 Car car new Car create new object Form form2 new Form car Create new form and pass the car that I ve creat
  • 源地图请求导致 404 错误

    更新到 Chrome 29 后 我注意到浏览器尝试从应用程序根目录获取 jquery min map 但在从资产收到之前提出请求 小名声不允许我发布屏幕图像进行校对 当然 我可以在浏览器设置中关闭源映射 如下所示question https
  • LdapConnection SearchRequest 抛出对象不存在错误

    我正在尝试查询 LDAP 服务器以查找 LDAP 用户并将其导入到我的系统中 但是 当我尝试执行此操作时 请求会抛出DirectoryOperationException 说The object does not exist ldapCon
  • 如何使用纯 GDI 对画布区域进行颜色混合(按指定的 alpha 值着色)?

    我想使用纯颜色混合画布区域 按指定的 alpha 值着色 Windows GDI http msdn microsoft com en us library dd145203 28v vs 85 29 aspx 因此没有 GDI Direc
  • PowerShell 脚本将文件(但不包括子文件夹)复制到 SFTP,并在完成后移动到子文件夹

    我正在使用以下脚本将文件从本地文件夹复制到 SFTP 上传文件后 我想将文件移动到子文件夹中 我只想上传以下文件C Users Administrator Desktop ftp文件夹 而不是其他子文件夹中的文件 param backupP
  • 如何防止模型无效?

    我是最佳实践的坚定倡导者 尤其是在角度方面 但我无法使用全新的 validators管道功能应有的样子 情况非常简单 1 个输入通过指令增强 使用 parser formatter还有一些 validators
  • 计数累计和

    我想知道是否可以对计数进行累积和 我想举的一个例子是今年影响美国的风暴 我想要一个列出 2014 年月份的结果集 以及该月之前影响美国的风暴累计总数 我希望得到 3 列的内容 Month NumberofStorms 和 Cumulativ
  • Indy FTP EIAcceptTimeout 异常

    我正在测试 IndyFTP 将文件上传到服务器 这文件已上传但有 0 字节因为出现了 EIdAccessTimeout 异常 Accept timed out 我该如何防止该异常 我的代码是否不正确 代码如下所示 procedure TFo
  • 从 perl 中的外部 *nix 命令获取 STDOUT、STDERR 和响应代码

    我想从 Perl 脚本中执行外部命令 将 stdout 和 stderr 的输出放入 variable我的选择 并将命令的退出代码放入 多变的 我经历过解决方案perlfaq8 http perldoc perl org perlfaq8
  • 打印 JTextField 在控制台上显示空白

    我是Java新手 刚刚尝试了Java的swing 我尝试制作一个登录表单 将JTextField的内容打印到控制台 但是当我尝试它时 控制台没有显示任何内容 这是我的代码 import java awt EventQueue import
  • 如何在角度中对取消订阅功能进行单元测试

    我想找到一种方法来测试订阅和主题上的取消订阅函数调用 我想出了一些可能的解决方案 但每一种都有优点和缺点 请记住 我不想出于测试目的而更改变量的访问修饰符 通过反射访问组件的私有变量 在这种情况下 我有一个存储订阅的私有类变量 组件 ts