Home > Mobile >  How to mock an object and verify a given parameter was provided to this mock
How to mock an object and verify a given parameter was provided to this mock

Time:05-10

I'm trying to test an HttpInterceptor, with the help of ng-mocks:

    @Injectable()
    export class AuthTokenInterceptor implements HttpInterceptor {
      constructor(private store: Store) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const currentToken = this.store.selectSnapshot(state => state.accounts.accessToken);
    
        if (currentToken) {
          req = req.clone({
            setHeaders: { Authorization: `Bearer ${currentToken}` },
          });
        }
        return next.handle(req);
      }
    }

I'm having trouble to see how I could provide the next parameter, especially since I want to check that the object has the setHeaders property present(or not):

    describe('Unauth guard test', () => {
      beforeEach(() => {
        return MockBuilder(AuthTokenInterceptor, AppModule).mock(Store);
      });
    
      it('should allow access if not authenticated', () => {
        //Arrange
        const fakeToken = 'fakeToken';
        const storeDispatchSpy = MockInstance(Store, 'selectSnapshot', jasmine.createSpy().and.returnValue(fakeToken));
        const httpHandlerSpy = MockInstance(HttpHandler, 'handle', jasmine.createSpy().and.returnValue(fakeToken));
        const fixture = MockRender(AuthTokenInterceptor);
        const interceptor = fixture.point.componentInstance;
       const request = new HttpRequest('GET', 'http://localhost:4200/');
    
        //Act
        const result = interceptor.intercept(request, httpHandlerSpy.???);//How to provide a mock of HttpHandler?
    
        //Assert
        expect(storeDispatchSpy).toHaveBeenCalled();
        expect(httpHandlerSpy).toHaveBeenCalledOnceWith(???);//How to verify that one parameter of the HttpRequest is set to specific value?
      });
    });

But how to provide a mocked instance to the intercept method? and more complex, how to check that my spy have been called with an object that has a specific value?

CodePudding user response:

In your case, you need to provide mockStore isolate your interceptor from other interceptors.

An example from ng-mocks docs and http interceptors.

https://codesandbox.io/s/intelligent-stallman-9bwup0?file=/src/test.spec.ts

describe('AuthTokenInterceptor', () => {
  beforeEach(() => {
    return (
      MockBuilder(AuthTokenInterceptor, AppModule)
        // required for interceptors
        .exclude(NG_MOCKS_INTERCEPTORS)
        .keep(HTTP_INTERCEPTORS)

        .replace(HttpClientModule, HttpClientTestingModule)
    );
  });

  it('adds header', () => {
    // creating an empty fixture
    const fixture = MockRender('', null, false);

    // stubbing store
    const store = ngMocks.findInstance(Store);
    ngMocks.stubMember(store, 'selectSnapshot', callback =>
      callback({
        accounts: {
          accessToken: 'Testing',
        },
      }),
    );

    // render
    fixture.detectChanges();

    // instances to test how HttpClient uses interceptors
    const client = ngMocks.findInstance(HttpClient);
    const httpMock = ngMocks.findInstance(HttpTestingController);

    // Let's do a simple request.
    client.get('/target').subscribe();

    // Now we can assert that a header has been added to the request.
    const req = httpMock.expectOne('/target');
    req.flush('');
    httpMock.verify();

    // asserting headers
    expect(req.request.headers.get('Authorization')).toEqual(
      'Bearer Testing',
    );
  });
});
  • Related