Search code examples
angularunit-testingjasminepipekarma-jasmine

Angular unit test pipe is not a function


I am getting the error this.targetAccounts$.pipe is not a function when running the unit test and I am not sure what I need to add.

class:

export class GenerateQrCodeComponent implements OnInit {       

targetAccounts$: Observable<IBWAccount[]>; 

constructor(private thirdPartyTransactionService: ThirdPartyTransactionService) {}
            
 ngOnInit() { 
      this.targetAccounts$ =
           this.thirdPartyTransactionService.targetAccountsForQrCode$;
      this.targetAccounts$.pipe(first()).subscribe((accounts) => {
           this.handleTargetChange(accounts[0]);
      });
      this.targetAccounts$.subscribe((accounts) => {
            this.targetAccounts = accounts;
      }); 
   }
}

Unit test:

describe('GenerateQrCodeComponent', () => {
    let component: GenerateQrCodeComponent;
    let fixture: ComponentFixture<GenerateQrCodeComponent>;

const mockThirdPartyTransactionService = {
        targetAccountsForQrCode$: () => of({}),
    };

beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [
                GenerateQrCodeComponent,
            ],
            imports: [
                TranslateModule.forRoot(),
                ReactiveFormsModule,
                FormsModule,
                BrowserAnimationsModule,
                IonicModule,
            ],
            providers: [
                {
                    provide: ThirdPartyTransactionService,
                    useValue: mockThirdPartyTransactionService,
                },
            ],
        }).compileComponents();

        fixture = TestBed.createComponent(GenerateQrCodeComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    }));

    it('should create', () => {
        expect(component).toBeTruthy();
    });
});

Solution

  • I think you are mocking targetAccountsForQrCode$ wrong, based on your code, targetAccountsForQrCode$ is a property class from the service, not a function, so mocking it could be like this:

    const mockThirdPartyTransactionService = { targetAccountsForQrCode$: of({})};
    

    If targetAccountsForQrCode$ is a function, try replacing your mock mockThirdPartyTransactionService using createSpyObj from jasmine like the following:

    const mockTransactionService = 
     jasmine.createSpyObj<ThirdPartyTransactionService>(
      'ThirdPartyTransactionService', 
      ['targetAccountsForQrCode$']
    );
    
    beforeEach(() => mockTransactionService.targetAccountsForQrCode.and.returnValue(of({})))
    
    beforeEach(async() => {
      TestBed.configureTestingModule({
       declarations: [...],
       imports: [...],
       providers: [
         { 
           provide: ThirdPartyTransactionService, 
           useValue: mockTransactionService 
         }
       ]
      })
    })