我用的是这个
import * as ObservableEvents from 'rxjs/Observable/fromEvent';
spyOn(ObservableEvents, 'fromEvent').and.returnValue(new Subject<any>().asObservable());
我得到的错误:
错误:: fromEvent未声明为可写或没有设置器
答案 0 :(得分:1)
您需要监视rxjs的属性。使用spyOnProperty将解决该错误。试试这个
res = ([], [])
for s in strings:
res["update" in s].append(s)
no_update, with_update = res
您也可以使用类似的方法将其添加到getter / setter中
>>> print(with_update)
['Beta_Gambus_teta_wqtr_update_2017.02.1277.ctr', 'Beta_Gambus_teta_tpesdr_update_2017.02.1277.ctr', 'Beta_Gambus_teta_cnms_update_2018.02.1279.ctr']
>>> print(no_update)
['Beta_Gambus_teta_wqtr_2017.02.1276.ctr', 'Beta_Gambus_teta_tpsedr_2017.02.1276.ctr', 'Beta_Gambus_teta_cnmsr_2018.02.1279.ctr']
希望这会有所帮助
答案 1 :(得分:1)
您不能监视模块导入,因为它是只读的。 Here's和GitHub中的Jasmine issue都是相同的rxjs问题。
但是,您真的要监视fromEvent
函数吗?如果您要检查类/函数是否调用fromEvent
,则不要这样做。测试应测试API,但不测试实现。很难维护这样的测试,即测试实现。您应该测试黑匣子,而不应该考虑它们的实现方式。
如果您要在测试内部使用fromEvent
,则测试其行为就不是问题。如果无论如何对您来说很重要,要测试事件如何转换为可观察对象,您可以创建一个“ fromEvent”包装器并对其进行模拟,例如:
class EventTransformer {
transform<T>(target: FromEventTarget<T>, eventName: string): Observable<T> {
return fromEvent(target, eventName);
}
}
class MyClass {
constructor(private eventTransformer: EventTransformer) {}
doSomething() { /* transform some event */ }
}
it('test', () => {
const eventTransformer = jasmine.createSpyObj<EventTransformer>(EventTransformer.name, [
'transform',
]);
eventTransformer.transform.and.returnValue(of({}));
const myClass = new MyClass(eventTransformer)
myClass.doSomething();
});
Another workaround,是通过更新测试tsconfig来使用“ 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",
},
答案 2 :(得分:0)
补充Omair的答案。就我而言,我需要在returnValue
语句上有一个函数。
const fromEventSpy = spyOnProperty(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));
干杯!
答案 3 :(得分:0)
允许监视模块的 Angular +10 解决方案“import * as XXX from 'abc'”
添加到 tsconfig.spec.json
"compilerOptions": {
"module": "commonjs",
"target": "es5",
...
},
props module 和 target 都很重要!除非目标设置为 es5 并且模块不是 commonjs,否则这将不起作用;
现在在您的规范文件中,您可以执行以下操作:
import * as selectors from '@app/state';
const mockModuleFunc = (importModule: any, methodName: string, returnValue: any = null) => {
let currentVal = importModule[methodName];
const descriptor = Object.getOwnPropertyDescriptor(importModule, methodName);
if(!descriptor.set) {
Object.defineProperty(importModule, methodName, {
set(newVal) {
currentVal = newVal;
},
get() {
return currentVal;
},
enumerable: true,
configurable: true
});
}
/**
* This actually works now and doesn't throw "is not declared writable or has no setter" error.
* Use spyOn as always, example with parameterized ngrx selectors:
*/
return spyOn(importModule, methodName).and.returnValue(() => returnValue);
}
// Usage example
it('Your test description', () => {
const spy = mockModuleFunc(selectors, 'yourFunctionToSpyOn', 'xyz');
...
})