问题
In my Angular 4 application, I need to test a method of a Service which at some point it calls a private method of the same service having:
window.location.replace(url);
When the test reach that line, the karma-runner browser gets redirected to the url
which of course is not what I want.
If I try to spy it, I get:
Error: <spyOn> : replace is not declared writable or has no setter
How can I correctly test my method?
回答1:
location
object is read-only property, and its properties are read-only as well.
The best test-friendly strategy is to not use native objects directly but via DI, because testabiliry is one of main benefits of DI.
document
already has DOCUMENT
provider abstraction, the same can be done for window
entirely, similarly to AngularJS $window
service:
const WINDOW = new InjectionToken('window');
function getWindow() {
return window;
}
...
{ provide: WINDOW, useFactory: getWindow }
...
...
constructor(@Inject(WINDOW) public window) {
this.window.location.replace(...);
}
...
In this setup WINDOW
provider can be stubbed in tests, and globals can be thoroughly tested.
Alternatively, providers can be created for each global in use.
来源:https://stackoverflow.com/questions/45926375/angular-testing-service-method-with-window-location-replace