TranslocoLocale pipes injected into a service causes unit test errors

1k Views Asked by At

How can I test a service that uses TranslocoLocale pipes (TranslocoDecimalPipe, TranslocoDatePipe, etc.)? I could obviously mock the pipes myself but I shouldn't have to.

TranslocoLocale pipes in my component templates work correctly in unit tests. Using the pipes in a service, by injecting them in the constructor, causes the unit tests to break. It will either complain that the pipe has no provider, or that ChangeDetectorRef has no provider.

In the example below, My service uses the TranslocoDecimalPipe. In my test I get the error:

NullInjectorError: StaticInjectorError(DynamicTestModule)[L10nTestService -> TranslocoDecimalPipe]: 
  StaticInjectorError(Platform: core)[L10nTestService -> TranslocoDecimalPipe]: 
    NullInjectorError: No provider for TranslocoDecimalPipe!
import { Injectable } from '@angular/core';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { TranslocoModule } from '@ngneat/transloco';
import { TranslocoDecimalPipe, TranslocoLocaleModule } from '@ngneat/transloco-locale';

@Injectable({ providedIn: 'root' })
class L10nTestService {
  decimalValue: string;

  constructor(private translocoDecimalPipe: TranslocoDecimalPipe) {
    this.decimalValue = translocoDecimalPipe.transform(1234567890.123456);
  }
}

describe('L10ntestService', () => {
  let spectator: SpectatorService<L10nTestService>;
  const createService = createServiceFactory<L10nTestService>({
    service: L10nTestService,
    imports: [
      TranslocoModule,
      TranslocoLocaleModule.init()
    ],
    providers: [TranslocoDecimalPipe]
  });

  beforeEach(() => spectator = createService());

  it('decimal value should be transformed', () => {
    expect(spectator.service.decimalValue).toBe('1,234,567,890.123');
  });
});
2

There are 2 best solutions below

0
On

This is how I mocked my TranslocoPipe and check that it is being called with the right arguments.

I want to test:

<p [innerHTML]="'MY.TRANSLATION.KEY' | transloco : { date: expectedDeliveryDate, time: localizedExpectedDeliveryDate }"></p>

So in my test I used:

const fakeTransform = (...args: string[]) => JSON.stringify(args);
const translocoPipeMock = jasmine.createSpy().and.callFake(fakeTransform);

Using ng-mock and the MockBuilder I replace the original pipe with the mock using:

.mock(TranslocoPipe, translocoPipeMock)

Then I can just assert like this:

expect(translocoPipeMock).toHaveBeenCalledWith('MY.TRANSLATION.KEY', {
  date: theMockedDate,
  time: theMockedTime,
});
0
On

I could make it work with ng-mock. Just like this:

imports: [
  ...,
  MockModule(TranslocoLocaleModule),
],