Search code examples
typescriptangular6karma-jasminets-mockito

How to test await toPromise() inside async function? (.toPromise() is not a function error)


Based on this question, I wrote this test:

it('call service when search product by code', async() => {
    let code: string = 'CODE';
    let product: Product = createProduct();
    let properties: ProductProperties = createProductProperties();
    when(mockProductService.getProductByCode(code)).thenReturn(of(product));
    when(mockProductService.getProductProperties(product.id)).thenReturn(of(properties));

    let result: Product = await sut.searchProductByCode(code);

    expect(result.code).toEqual(product.code);
    expect(result.properties).toEqual(properties);
    verify(mockProductService.getProductByCode(code));
    verify(mockProductService.getProductProperties(product.id));
  });

The function I'm testing is:

async searchProductByCode(code: string): Promise<Product> {
    let product = await this.productService.getProductByCode(code).toPromise(); //fails running test
    product.properties = await this.productService.getProductProperties(product.id).toPromise();
    return product;
  }

The function runs OK but the test fails:

TypeError: this.productService.getProductByCode(...).toPromise is not a function

Is like I'm not correctly mocking the service?

The method productService.getProductByCode() returns an Observable of Product:

getProductByCode(code: string): Observable<Product>

The method of(product) creates an Observable object of product. And method .toPromise() is a method from Observable, that returns a promise from the observable. Here the import:

import { of } from 'rxjs';

Solution

  • Finally, changing my keywords to search about it, I've got a good answer. I was mocking my service badly.

    This (my code) is wrong:

    beforeEach(() => {
        mockProductService = mock(ProductService);
        mockStationService = mock(StationService);
    
        sut = new QuickStationChangeComponentService(
          mockProductService,
          mockStationService,
        );
      });
    

    To make it works, it needs an instance:

    beforeEach(() => {
        mockProductService = mock(ProductService);
        mockStationService = mock(StationService);
    
        sut = new QuickStationChangeComponentService(
          instance(mockProductService),
          instance(mockStationService),
        );
      });
    

    I was focusing on a wrong way to approach it to search.

    If you, like me, are used to Java and think that mock(class) returns a mocked instance of class, you are wrong. If you want an instance like in my tests, you need to create an instance of mock.