I'm struggling to get my test to work for a CanLoad
method for my route.
That is the code I would like to test:
@Injectable()
export class ContractGuard implements CanLoad {
constructor(private router: Router, private contractService: ContractService) { }
public canLoad(route: Route): Observable<boolean> | Promise<boolean> | boolean {
return this.contractService.getContracts().map((contracts: Array<Contract>) => {
// My test does not hit this spot
if (contracts) {
this.router.navigate([contracts[0].id, "Home"]);
return true;
}
return false;
}).catch(() => {
return Observable.of(false);
});
}
}
I've already created a mock with MockBackend
and the test runs, but the .map
of getContracts()
does not get called.
That is the test setup:
describe("ContractGuard", () => {
let contractGuard: ContractGuard;
let contractService: ContractService;
let router: Router;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ContractService,
MockBackend,
BaseRequestOptions,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: XHRBackend, defaultOptions: BaseRequestOptions) => new Http(backend, defaultOptions)
}
]
});
let contracts = Array<Contract>();
contracts.push(new Contract());
contracts.push(new Contract());
router = TestBed.get(Router);
contractService = TestBed.get(ContractService);
let backend = TestBed.get(MockBackend);
backend.connections.subscribe((connection: MockConnection) => {
connection.mockRespond(new Response(new ResponseOptions({ body: contracts })));
});
});
// TODO: To be continued
xit("should load app route", () => {
// Arrange
// Act
// Assert
});
});
How can I make my .map
to get called?
EDIT:
I completed my test, but map
still does not get called:
describe("ContractGuard", () => {
let contractGuard: ContractGuard;
let contractService: ContractService;
let router = {
navigate: jasmine.createSpy("navigate")
};
beforeEach(() => {
let contracts = Array<Contract>();
contracts.push(new Contract(1, 1, "KWK 1"));
contracts.push(new Contract(2, 1, "KWK 2"));
TestBed.configureTestingModule({
providers: [
{ provide: Router, useValue: router },
{ provide: ContractService, useValue: { getContracts: () => { return Observable.of(contracts); } } },
MockBackend,
BaseRequestOptions,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: XHRBackend, defaultOptions: BaseRequestOptions) => new Http(backend, defaultOptions)
}
]
});
router = TestBed.get(Router);
contractService = TestBed.get(ContractService);
let backend = TestBed.get(MockBackend);
backend.connections.subscribe((connection: MockConnection) => {
connection.mockRespond(new Response(new ResponseOptions({ body: contracts })));
});
});
it("should load app route", () => {
// Arrange
let guard = new ContractGuard(<any>router, contractService);
// Act
guard.canLoad(null);
// Assert
contractService.getContracts().subscribe((contracts) => {
expect(router.navigate).toHaveBeenCalled(); // False
expect(contracts.length).toBe(2); // True
});
});
});
EDIT:
Ok, I won't post this as answer, as IMO this is not the best way to solve the issue. I'm subscribing to canLoad
, but I wish, the router should be responsible for this.
That is the workaround:
it("should load app route", () => {
// Arrange
let guard = new VertragGuard(<any>router, contractService);
// Act & Assert
(<Observable<Boolean>>guard.canLoad(null)).subscribe(value => {
expect(value).toBeTruthy();
});
});