我如何从 RXJS 5.5.6 模拟 fromEvent 函数?

How can I mock fromEvent function from RXJS 5.5.6?

我必须测试一个使用 fromEvent 可观察函数的函数。 在升级到 '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 包装在一个我知道上下文的对象中。但是我想知道如何才能干净利落地解决这个问题。

提前致谢。

你是对的。 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

也许这有帮助?!

不知道你的情况是否如此,但如果你 spyOnPropertyfromEvent 上,它可能会起作用。

像这样:

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

在我的例子中,我导入了整个 rxjs

import * as rxjs from 'rxjs';

希望对您有所帮助, 干杯!

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

例如,您可能会遇到此错误或类似的错误:

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

因为捆绑器只是将那些单独的导出函数包装到 getter 属性 中,使得它们无法模拟。

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

例如,如果您使用的是 typescript,则需要更改 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() {}。这导致不用担心使用 spyOn,因为它被包裹在 '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')