Jest SpyOn -调用实际方法,而不是模拟实现

nwwlzxa7  于 2023-01-28  发布在  Jest
关注(0)|答案(2)|浏览(323)

我已经搜索了高和低,试图让我的笑话测试工作,但在我的搜索一无所获。
我有一个函数(createRoom),我想对它进行单元测试,我想模拟一个方法(gameFactory.createNewGameWithInitialPlayer())调用。

游戏服务.ts

const GameService = (games: {[index: string]: Game}) => {
  const playerFactory = PlayerFactory()
  const gameFactory = new GameFactory()

  const createRoom = ({name, device, socketID}: {name: string, device: string, socketID: string}): RoomResponse => {
    const player = playerFactory.createNewPlayer(name, device, socketID)

    if (player && player.id) {
        const game: Game|undefined = gameFactory.createNewGameWithInitialPlayer(player)
        ...
    }
    ...
}

游戏工厂.ts

export class GameFactory {
    createNewGameWithInitialPlayer = (player: Player): Game|undefined => {
        const game = new Game()
        game.spectators[player.id as any as number] = player

        return game
    }
}

游戏服务测试ts

import * as gameFactory from '../Factories/GameFactory'

describe('Testing Game Service', () => {
    test('createRoom', () => {
        jest.spyOn(gameFactory, 'GameFactory').mockReturnValue({ createNewGameWithInitialPlayer: jest.fn().mockReturnValue(undefined)})

        const response: RoomResponse = gameService.createRoom({
            name: 'Player 1',
            device: DevicesEnum.ios,
            socketID: 'some-socket-id'
        })
    ...
    }
    ...
}

GameService.test.ts中,我模拟了createNewGameWithInitialPlayer方法调用的返回值。然而,当我运行测试时,运行的是它的 * 实际 * 实现,而不是我模拟的版本。特别是对于这个测试,我希望createNewGameWithInitialPlayer方法返回undefined,但这并没有发生,它似乎在调用实际的方法实现。

pbpqsu0x

pbpqsu0x1#

如果你想覆盖 createNewGameWithInitialPlayer 并返回你想要的,你必须在测试中模拟GameFactory类的导入。

// Here you are creating your mock and saying the default return Game object
const mockCreateNewGameWithInitialPlayer = jest.fn().mockImplementation(() => new Game());

// Here you say to jest that any file who wants to import "GameFactory"
// will import this fake class
jest.mock('rootofGameFactory/GameFactory', () => ({
    GameFactory: function(){
      return {
        // and when any file wants to execute this method, will execute my mock
        createNewGameWithInitialPlayer: mockCreateNewGameWithInitialPlayer
      }
    }
}))

describe('Testing Game Service', () => {
    test('createRoom', () => {
        const response: RoomResponse = gameService.createRoom({
            name: 'Player 1',
            device: DevicesEnum.ios,
            socketID: 'some-socket-id'
        })
    ...
    }
    ...
}

如果你想改变你的模拟方法的返回对象,你必须这样做...

test('createRoom 2', () => {
        //Here you say to jest, just ONCE (for this test) return an instance of Game2
        mockCreateNewGameWithInitialPlayer.mockImplementationOnce(() => new Game2())
        const response: RoomResponse = gameService.createRoom({
            name: 'Player 1',
            device: DevicesEnum.ios,
            socketID: 'some-socket-id'
        })
    ...
    }
5t7ly7z5

5t7ly7z52#

玩笑文件提到
默认情况下,jest.spyOn还会调用spied方法,这是与大多数其他测试库不同的行为,如果想要覆盖原始函数,可以使用jest.spyOn(object,methodName).mockImplementation(()=〉customImplementation)或jest.replaceProperty(object,methodName,jest.fn(()=〉customImplementation));
所以你可以这样做

jest.spyOn(gameFactory, 'GameFactory').mockImplementation(() => { return undefined })

相关问题