【发布时间】:2020-07-04 05:35:46
【问题描述】:
编辑:
事实证明,问题不是我在此处提供的代码部分,而是我忽略的部分。我不会删除问题,以防有人发现示例和答案有用。
我需要使用 Jest 测试 Angular 服务。 GameService 有一个 start 方法,它调用 manage 方法。为了测试start,我只需要监视manage 以检查它是否被调用,但要避免它的实际执行。
jest.spyOn() 方法本身不会覆盖方法的原始实现。需要自己提供该实现。文档提出了两种方法:
jest.spyOn(gameService, 'manage').mockImplementation(() => {});gameService.manage = jest.fn(() => {});
但是,尽管这两种方法都允许我监视 manage 的调用,但它们并没有避免执行实际的 manage 方法。
这似乎是a recurrent problem,但我还没有找到适合我的解决方案。我只是想知道是否有人在 Angular 中遇到过类似的问题并且可以找到解决方案。
我的服务代码及其规范如下(我将省略不相关的测试用例):
game.service.ts
import { Injectable } from '@angular/core';
import { OneDeviceModule } from '../one-device.module';
import { PlayersService } from './players.service';
import { Player } from '../../models/player';
@Injectable({
providedIn: OneDeviceModule
})
export class GameService {
public players: Player[];
constructor(private playersService: PlayersService) { }
public start(): void {
const players = this.playersService.getPlayersList();
if (players.length < 2) {
throw new Error('There must be at least two players to start the game');
}
this.players = players;
this.manage();
}
public manage(): void {
while(this.goesOn()) {
}
}
public goesOn(): boolean {
return true;
}
}
game.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { mocked } from 'ts-jest/utils';
import { GameService } from './game.service';
import { PlayersService } from './players.service';
import { Player } from '../../models/player';
jest.mock('./players.service');
const mockedPlayersService = mocked(PlayersService, true);
const players = [
new Player('John'),
new Player('Anna'),
new Player('Julia')
];
describe('GameService', () => {
let gameService: GameService;
let playersService: PlayersService;
beforeEach(() => {
TestBed.configureTestingModule({ providers: [GameService, PlayersService]});
gameService = TestBed.inject(GameService);
playersService = mockedPlayersService.mock.instances[0];
(playersService.getPlayersList as jest.Mock).mockReturnValue(players);
});
afterEach(() => {
mockedPlayersService.mockClear();
(playersService.getPlayersList as jest.Mock).mockClear();
});
describe('constructor', () => {
...
});
describe('start', () => {
function onePlayerSetup(playersService: PlayersService): void {
(playersService.getPlayersList as jest.Mock).mockClear();
(playersService.getPlayersList as jest.Mock).mockReturnValue([new Player('John')]);
}
const mockManage: jest.Mock<void, never[]> = jest.fn().mockImplementation(() => {});
...
it('should not call manage method if there are less than 2 players', () => {
onePlayerSetup(playersService);
gameService.manage = mockManage;
try { gameService.start(); }
catch { }
finally { expect(mockManage).toHaveBeenCalledTimes(0); }
});
it('should call manage method if everything is ok', () => {
gameService.manage = mockManage;
gameService.start();
expect(mockManage).toHaveBeenCalledTimes(1);
});
});
});
【问题讨论】:
标签: angular unit-testing jestjs spy