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?
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.
});
À 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()
.
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() }