如何从RXJS 5.5.6模拟fromEvent函数?

Llo*_*iol 8 unit-testing jasmine rxjs5 angular rxjs6

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

spyOn(Observable, 'fromEvent').and.callFake(mockFromEventFunction)
Run Code Online (Sandbox Code Playgroud)

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

import { fromEvent } from 'rxjs/observable/fromEvent';
Run Code Online (Sandbox Code Playgroud)

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

我建议这不起作用:

import * as FromEventContext from 'rxjs/observable/fromEvent';
...
spyOn(FromEventContext , 'fromEvent').and.callFake(mockFromEventFunction)
Run Code Online (Sandbox Code Playgroud)

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

提前致谢.

Llo*_*iol 3

经过一番调查后,我发现我们能否模拟这个单个导出函数直接取决于我们的捆绑器在测试时如何解析模块。

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

Error: : myFunctionName is not declared writable or has no setter
Run Code Online (Sandbox Code Playgroud)

原因是捆绑器只是将那些孤独的导出函数包装到 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",
  },
Run Code Online (Sandbox Code Playgroud)

commonjs 中模块的任何导出成员的最终输出将类似于:exports.myFunc = function() {}。这使得使用spyOn 无需担心,因为它包装在“导出”对象上。一个很好的用例是,它可以在任何地方被嘲笑,包括它自己的文件中的用法

例子:

// 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')
Run Code Online (Sandbox Code Playgroud)