如何从RXJS 5.5.6模拟fromEvent函数?

时间:2018-01-24 11:03:28

标签: angular unit-testing jasmine rxjs5 rxjs6

我必须测试一个使用 fromEvent observable函数的函数。 在升级到' lettable'之前运营商,我只是这样做:

spyOn(Observable, 'fromEvent').and.callFake(mockFromEventFunction)

但是现在,Rxjs发生了变化, Observable.fromEvent 只是一个名为 fromEvent 的函数,它是这样导入的:(并以相同的方式使用)

import { fromEvent } from 'rxjs/observable/fromEvent';

我的问题是,如何在不知道它的父上下文的情况下使用Jasmine间谍实用程序来模拟该函数?

我建议这不起作用:

import * as FromEventContext from 'rxjs/observable/fromEvent';
...
spyOn(FromEventContext , 'fromEvent').and.callFake(mockFromEventFunction)

现在我有一个解决方法将fromEvent包装在一个我知道上下文的Object中。但我想知道如何干净利落地解决这个问题。

提前致谢。

3 个答案:

答案 0 :(得分:1)

经过一番调查,我发现我们可以模拟或不能模拟单个导出函数的事实直接取决于我们的捆绑程序在测试时如何解析模块。

因此,例如,您可能偶然发现此错误或类似情况:

Error: : myFunctionName is not declared writable or has no setter

由于捆绑程序只是将那些孤独导出的函数包装到一个getter属性中,导致它们无法被模拟而导致。

我最终使用的解决方案是在测试时'commonjs' 中编译模块。

例如,如果您使用的是打字稿,则需要将tsconfig.spec.ts更改为使用commonjs模块:

"compilerOptions": {
     ....
      // force commonjs module output, since it let mock exported members on modules to anywhere in the application (even in the same file)
      "module": "commonjs",
  },

commonjs中模块的任何导出成员的结果输出将像:exports.myFunc = function() {}。不必担心,因为它被包装在'exports'对象上,因此无需担心。一个很好的用例是,它将在任何地方进行模拟,包括其自己文件中的用法

示例:

// some-module.js
export function functionToMock() {
     return 'myFuncToMock';
}
export function functionToTest() {
     return functionToMock();
}

// testing-module.spec.js
import * as SomeModule from ./some-module
spyOn(SomeModule, 'functionToMock').and.returnValue('mockedCorrectly');
SomeModule.functionToTest().toBe('mockedCorrectly')

答案 1 :(得分:0)

你是对的。 FromEventContext不适用于此。

相反,您可以使用jasmine-auto-spies,这将使处理此类事情更加容易。

import { Spy, createSpyFromClass } from 'jasmine-auto-spies';

现在,在测试代码中,您可以在Observables上创建间谍:

fakeObservable = createSpyFromClass(Observable);
fakeObservable.fromEvent.and.returnValue(Observable.empty()) // or whatever you want to return

也许这有帮助?!

答案 2 :(得分:0)

不知道是否适合您的情况,但是如果您在spyOnPropertyfromEvent可能会起作用。

赞:

spyOnProperty(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));

就我而言,我导入了整个rxjs

import * as rxjs from 'rxjs';

希望有帮助, 干杯!