web-dev-qa-db-fra.com

Comment remplacer fournisseur dans Angular 5 pour un seul test?

Dans l'un de mes fichiers de tests unitaires, je dois simuler plusieurs fois le même service avec des simulacres différents.

import { MyService } from '../services/myservice.service';
import { MockMyService1 } from '../mocks/mockmyservice1';
import { MockMyService2 } from '../mocks/mockmyservice2';
describe('MyComponent', () => {

    beforeEach(async(() => {
        TestBed.configureTestingModule({
        declarations: [
            MyComponent
        ],
        providers: [
            { provide: MyService, useClass: MockMyService1 }
        ]
        })
        .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MapComponent);
        mapComponent = fixture.componentInstance;
        fixture.detectChanges();
    });

    describe('MyFirstTest', () => {
        it('should test with my first mock', () => {
            /**
             * Test with my first mock
             */
        });
    });

    describe('MySecondTest', () => {
        // Here I would like to change { provide: MyService, useClass: MockMyService1 } to { provide: MyService, useClass: MockMyService2 }

        it('should test with my second mock', () => {
            /**
             * Test with my second mock
             */
        });
    });
});

Je vois que la fonction overrideProvider existe, mais je n’ai pas réussi à l’utiliser dans mon test. Lorsque je l'utilise dans un "it", le fournisseur ne change pas. Je n'ai pas réussi à trouver un exemple où cette fonction est appelée. Pourriez-vous m'expliquer comment l'utiliser correctement? Ou avez-vous une autre méthode pour le faire?

4
hbaltz

Si le service est injecté en tant que propriété publique, par exemple:

@Component(...)
class MyComponent {
  constructor(public myService: MyService)
}

Vous pouvez faire quelque chose comme:

it('...', () => {
  component.myService = new MockMyService2(...); // Make sure to provide MockMyService2 dependencies in constructor, if it has any.
  fixture.detectChanges();

  // Your test here...
})

Si le service injecté est stocké dans une propriété privée, vous pouvez l'écrire sous la forme (component as any).myServiceMockMyService2 = new MockMyService2(...); pour contourner TS.

Ce n'est pas joli mais ça marche.

En ce qui concerne TestBed.overrideProvider, je n’ai pas eu de chance avec cette approche (ce qui serait bien mieux si cela fonctionnait):

it('...', () =>{
  TestBed.overrideProvider(MyService, { useClass: MockMyService2 });
  TestBed.compileComponents();
  fixture = TestBed.createComponent(ConfirmationModalComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();

  // This was still using the original service, not sure what is wrong here.
});
1
Filip Voska

À partir de 6 angulaires, j'ai remarqué que overrideProvider fonctionne avec la propriété useValue. Donc, pour que cela fonctionne, essayez quelque chose comme:

class MockRequestService1 {
  ...
}

class MockRequestService2 {
  ...
}

alors écrivez votre TestBed comme:

// example with injected service
TestBed.configureTestingModule({
  // Provide the service-under-test
  providers: [
    SomeService, {
      provide: SomeInjectedService, useValue: {}
    }
  ]
});

Et chaque fois que vous souhaitez remplacer le fournisseur, utilisez simplement:

TestBed.overrideProvider(SomeInjectedService, {useValue: new MockRequestService1()});
// Inject both the service-to-test and its (spy) dependency
someService = TestBed.get(SomeService);
someInjectedService = TestBed.get(SomeInjectedService);

Dans une fonction beforeEach() ou placez-le dans une fonction it().

1

Cela a juste fonctionné pour moi (angulaire 7.x):

 imports: [ MyCoreModule.forRoot()],
 providers: [{provide: LoginService, useValue: new LoginServiceMock()}]

Le service de connexion fait partie de MyCoreModule mais je peux le remplacer par le fournisseur factice. De plus, si vous utilisez useValue, n'oubliez pas le nouveau votreService ()

{ provide: MyService, useValue: new MockMyService1() }
0
David Dehghan