Zombar de uma propriedade Subject de serviço simulado a ser inscrito no teste de unidade Angular
Em meu teste de unidade Angular, meu serviço simulado tem duas propriedades:
public messageChange: Subject<ChatMessage> = new Subject<ChatMessage>();
public gameChange: Subject<GameState> = new Subject<GameState>();
E no meu SUT eu os uso no meu construtor:
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);
});
No momento, estou tentando usar essas 2 abordagens para simular propriedades de serviço simulado:
- Assunto de simulação de repetição de teste de unidade angular
- Como espionar uma propriedade de valor (em vez de um método) com Jasmine
Agora meu teste se parece com este:
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();
});
}
Então, no teste, eu crio:
simulação de serviço
hubServiceMock
,falso
messageChange = new Subject();
,falso
gameChange = new Subject();
,eu corro para ambos
.next
,e eu configurei o espião para propriedades:
spyOnProperty(hubServiceMock, 'messageChange', 'get').and.returnValue( messageChange );
spyOnProperty(hubServiceMock, 'gameChange', 'get').and.returnValue( gameChange );
Por que não funciona comigo? Recebo um erro:
Não é possível ler a propriedade 'subscrever' de indefinido
Respostas
Não funciona porque hubServiceMock
não contém os assuntos falsos messageChange
e gameChange
, você precisa configurá-los antes de ligar 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;
então deve funcionar, talvez pequenos ajustes sejam necessários.
Eu sugeriria usar uma biblioteca de zombaria para tais casos, para evitar dor.
Por exemplo, com ng-mocks , o teste pode ser parecido com:
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.
});
}
Acabei com a abordagem, onde injeto um serviço simulado como este:
hubServiceMock = TestBed.inject(HubConnectionService);
Então eu ridicularizo meus Subject
s assim:
it('Service_ShouldBeCreated', () => {
spyOn(hubServiceMock.messageChange, 'next');
spyOn(hubServiceMock.gameChange, 'next');
expect(signalrService).toBeTruthy();
});
E em outros testes, posso usar métodos de serviço simulado como este:
let spyIsConnectionStarted = spyOn(hubServiceMock, 'isConnectionStarted');
spyIsConnectionStarted.and.returnValue(true);