2

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();
  });
});
DAG
  • 2,460
  • 5
  • 33
  • 61
  • I don't tag it as duplicate because it's not exactly the same question but this might help you: https://stackoverflow.com/questions/41218323/how-to-unit-test-canactivate-guard-method-of-angular2-using-jasmine – Supamiu Aug 04 '17 at 15:12
  • different cases. this one you mentioned has no http request, it's easier to test, my problem is basically with the observable which is not the case in this link you referenced – DAG Aug 04 '17 at 15:17
  • The only thing you need at the moment is to test it, your implementation is fine and the router will handle this as if it was the example in the question I linked, I think that you can test it as it is tested in the question. The only thing you need to change is the expectation, as you want to test is in an asynchronous way (subscribe and expect in the subscription). – Supamiu Aug 04 '17 at 15:19
  • Hi @Supamiu check my update. I did as you said. It still does not work. I had already tried this before. I don't know what else I can do to make map called – DAG Aug 04 '17 at 17:53

0 Answers0