【问题标题】:spyOn method in constructor with jasmine茉莉花的构造函数中的 spyOn 方法
【发布时间】:2016-09-24 06:38:01
【问题描述】:

我想在我的单元测试中监视一个承诺并伪造该承诺,但问题是如果我首先运行构造函数,那么他首先运行承诺然后运行 ​​Spyon 的问题。

但是当我第一次运行 spyOn 然后构造函数时,它给出了一个错误,即存储未定义。

有人知道如何解决这个问题吗?

规格文件:

   describe('Settings Service', () => {

    beforeEach(() => {
        settingsService = new SettingsService(); // This gives a error beceause it runs the promise 
        spyOn(settingsService.storage, 'get').and.callFake((key: String): Promise<string> => {
            return new Promise((resolve, reject) => { resolve('url'); });
        });
    });

构造函数:

constructor() {
        this.storage = new Storage(LocalStorage);
        this.storage.get('url').then(data => {
            this.setLink(data);
        });
    }

更新:

我也试过这个:

let injector: any = ReflectiveInjector.resolveAndCreate([SettingsService]);
    settingsService = injector.get(SettingsService);

    spyOn(settingsService.storage, 'get').and.callFake((key: String): Promise<string> => {
        return new Promise((resolve, reject) => { resolve('https://secure.info/pascal'); });
    });

【问题讨论】:

  • “简单”的第一种方法可能是注入 Storage 而不是在构造函数中创建实例。然后,您可以在调用构造函数之前模拟这个注入的存储
  • 你有例子吗?
  • 你将SettingsService 实现为一个角度服务,然后你将它注入你的类中:类似于static $inject = ['settingsService']; constructor(private settingsService: SettingsService) {...} 然后你可以在你的测试中使用$injector.get('settingsService') 和mock 获得这个服务的副本它或窥探它
  • 这就是我现在拥有的
  • 对不起,我想说,你应该注入Storage

标签: unit-testing typescript angular jasmine karma-runner


【解决方案1】:

您遇到的问题是您在构造函数中实例化 Storage,因此您无法从外部访问它。这意味着你不能模拟它。

在调用settingsService = new SettingsService(); 之前设置spyOn 也不起作用,因为尚未创建字段存储。

你有两种方法可以解决这个问题:

使用以下代码模拟服务 $httpBackend。以this post为例来看看

beforeEach(inject(function($injector) {
    service = $injector.get('carService');
    $httpBackend = $injector.get('$httpBackend');

    $httpBackend.when('GET', "/api/cars/types").respond(["Toyota", "Honda", "Tesla"]);
}));

这样您可以模拟调用this.storage.get('url') 时获得的承诺并测试行为。

使 Storage 成为服务并模拟注入它:如果您使用这种方法,您可以模拟 Storage 并因此模拟 this.storage.get('url') 的行为。你的类的代码 `` 看起来像这样

static $inject = ['Storage'];
constructor(storage: Storage) {
    this.storage = storage;
    this.storage.get('url').then(data => {
        this.setLink(data);
    });
}

但是这种方式取决于你如何定义和使用存储所以一般第一种方式会更好

【讨论】:

  • 这是 angular 1 但我使用 angular 2
  • 好点,我没有看到标签。无论如何,我认为不会有太大的不同
猜你喜欢
  • 2014-03-29
  • 2021-12-12
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 2013-06-29
  • 1970-01-01
相关资源
最近更新 更多