Se moquer d'une propriété Subject d'un service simulé à souscrire dans le test unitaire angulaire
Dans mes tests unitaires angulaires, mon service simulé a deux propriétés:
public messageChange: Subject<ChatMessage> = new Subject<ChatMessage>();
public gameChange: Subject<GameState> = new Subject<GameState>();
Et dans mon SUT je les utilise dans mon constructeur:
this._subChat = this.hub.messageChange.subscribe((message: ChatMessage) => {
this.message = message;
this.messageChange.next(this.message);
});
this._subGame = this.hub.gameChange.subscribe((game: GameState) => {
this.game.setGame(game);
});
En ce moment, j'essaie d'utiliser ces 2 approches pour simuler des propriétés à partir d'un service simulé:
- Sujet de relecture simulée de test d'unité angulaire
- Comment espionner une propriété de valeur (plutôt qu'une méthode) avec Jasmine
Maintenant, mes tests ressemblent à ceci:
describe('SignalRService', () => {
let signalrService: SignalRService;
const hubServiceMock = jasmine.createSpyObj('HubConnectionService', [
'isConnectionStarted',
]);
const messageChange = new Subject();
const gameChange = new Subject();
beforeEach(() => {
signalrService = new SignalRService(
hubServiceMock
);
let msg = {} as ChatMessage;
let gam = {} as GameState;
messageChange.next(msg);
gameChange.next(gam);
});
it('Service_ShouldBeCreated', () => {
spyOnProperty(hubServiceMock, 'messageChange', 'get').and.returnValue(
messageChange
);
spyOnProperty(hubServiceMock, 'gameChange', 'get').and.returnValue(
gameChange
);
expect(signalrService).toBeTruthy();
});
}
Donc, dans le test, je crée:
maquette de service
hubServiceMock
,faux
messageChange = new Subject();
,faux
gameChange = new Subject();
,je cours pour les deux
.next
,et j'ai configuré l'espion pour les propriétés:
spyOnProperty(hubServiceMock, 'messageChange', 'get').and.returnValue( messageChange );
spyOnProperty(hubServiceMock, 'gameChange', 'get').and.returnValue( gameChange );
Pourquoi ça ne marche pas pour moi? Je reçois une erreur:
Impossible de lire la propriété 'subscribe' d'undefined
Réponses
Cela ne fonctionne pas car hubServiceMock
il ne contient pas les faux sujets messageChange
et gameChange
vous devez les définir avant d'appeler new SignalRService(hubServiceMock)
.
const hubServiceMock = jasmine.createSpyObj('HubConnectionService', [
'isConnectionStarted',
]);
const messageChange = new Subject();
const gameChange = new Subject();
// add this
hubServiceMock.messageChange = messageChange;
hubServiceMock.gameChange = gameChange;
alors cela devrait fonctionner, peut-être que de petits ajustements sont nécessaires.
Je suggérerais d'utiliser une librairie moqueuse pour de tels cas afin d'éviter la douleur.
Par exemple avec ng-mocks , le test pourrait ressembler à:
describe('SignalRService', () => {
beforeEach(() => MockBuilder(SignalRService, ITS_MODULE));
const hubServiceMock = {
messageChange: new Subject(),
gameChange: new Subject(),
};
beforeEach(() => MockInstance(HubConnectionService, hubServiceMock));
it('Service_ShouldBeCreated', () => {
const signalrService = MockRender(SignalRService).point.componentInstance;
expect(signalrService).toBeTruthy();
hubServiceMock.messageChange.next({});
hubServiceMock.gameChange.next({});
// next assertions.
});
}
Je me suis retrouvé avec une approche, où j'injecte un service simulé comme celui-ci:
hubServiceMock = TestBed.inject(HubConnectionService);
Puis je me moque des miens Subject
comme ceci:
it('Service_ShouldBeCreated', () => {
spyOn(hubServiceMock.messageChange, 'next');
spyOn(hubServiceMock.gameChange, 'next');
expect(signalrService).toBeTruthy();
});
Et dans d'autres tests, je peux utiliser des méthodes de service simulé comme ça:
let spyIsConnectionStarted = spyOn(hubServiceMock, 'isConnectionStarted');
spyIsConnectionStarted.and.returnValue(true);