首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NestJS TypeORM模拟存储库的数据源

NestJS TypeORM模拟存储库的数据源
EN

Stack Overflow用户
提问于 2022-07-18 08:10:53
回答 2查看 2.6K关注 0票数 1

我正在尝试模拟一个存储库。我不想做真正的数据库调用。我(认为我)正在遵循关于NestJS和某些堆栈溢出项的文档。

但是,当我运行测试时,我会得到以下错误:

代码语言:javascript
运行
复制
JwtStrategy › validate › throws an unauthorized exception as user cannot be found
Nest can't resolve dependencies of the UserEntityRepository (?). Please make sure that the argument DataSource at index [0] is available in the TypeOrmModule context.

Potential solutions:
- If DataSource is a provider, is it part of the current TypeOrmModule?
- If DataSource is exported from a separate @Module, is that module imported within TypeOrmModule?
  @Module({
    imports: [ /* the Module containing DataSource */ ]
  })

现在,据我所知,UserEntityRepository似乎没有被正确地模仿。由于它是用户服务类中的第一个(索引)依赖项:

./user.service.ts

代码语言:javascript
运行
复制
@Injectable()
export class UserService {
    constructor(
        @InjectRepository(UserEntity)
        private userRepository: Repository<UserEntity>
    ) {}

    async findOneBy({ username }): Promise<UserEntity> {
        return await this.userRepository.findOneBy({ username })
    }
}

./jwt.strategy.ts

代码语言:javascript
运行
复制
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
      private userService: UserService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET || config.get('jwt.secret'),
    })
  }

  async validate(payload: JwtPayload) {
    const { username } = payload;
    const user = await this.userService.findOneBy({username});

    if (!user) {
      throw new UnauthorizedException();
    }

    return user;
  }
}

./jwt.strategy.spect.ts

代码语言:javascript
运行
复制
const mockUserRepositoryFactory = jest.fn(() => ({
  findOneBy: jest.fn(entity => entity),
}));

describe('JwtStrategy', () => {
  let jwtStrategy: JwtStrategy;
  let userService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [UserModule],
      providers: [
        JwtStrategy,
        UserService,
        // shouldn't this correctly provide the datasource?
        {
          provide: getRepositoryToken(UserEntity),
          useFactory: mockUserRepositoryFactory,
        },

      ]
    }).compile();

    jwtStrategy = await module.get<JwtStrategy>(JwtStrategy);
    userService = await module.get<UserService>(UserService);
  });

  describe('validate', () => {
    it('validates and returns user based on JWT payload', async () => {
      const user = new UserEntity();
      user.username = 'TestUser';

      userService.findOneBy.mockResolvedValue(user);
      const result = await jwtStrategy.validate({ username: 'TestUser' });
      expect(userService.findOneBy).toHaveBeenCalledWith({ username: 'TestUser' });
      expect(result).toEqual(user);
    });

    it('throws an unauthorized exception as user cannot be found', async () => {
      userService.findOneBy.mockResolvedValue(null);
      expect(jwtStrategy.validate({ username: 'TestUser' })).rejects.toThrow(UnauthorizedException);
    });
  });
});

=====更新

在代码框中创建了一个最小的设置。

https://codesandbox.io/s/xenodochial-benz-kve4eq?file=/test/jwt.test.js

但是不知怎么的,测试选项卡没有显示在沙箱中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-05 08:14:18

首先,您必须模拟DataSource (如果您愿意,可以创建一个单独的文件)

代码语言:javascript
运行
复制
import { DataSource } from "typeorm";

// @ts-ignore
export const dataSourceMockFactory: () => MockType<DataSource> = jest.fn(() => ({
  <mock_function>: jest.fn(),
}));

export type MockType<T> = {
  [P in keyof T]?: jest.Mock<{}>;
};

然后创建一个测试文件

代码语言:javascript
运行
复制
describe('---MSG---', () => {
...
  let dataSourceMock: MockType<DataSource>
...
  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [],
      controllers: [<CONTROLLERS>],
      providers: [ <PROVIDERS>
        { provide: DataSource, useFactory: dataSourceMockFactory }],
    }).compile()
...
    dataSourceMock = module.get(DataSource);
...
  })

  describe('---MSG---', () => {
    it('---MSG---', async () => {
      await <Call mock function>
      expect(dataSourceMock.<DataSource mocked function>).toBeCalled();
    });
  })
票数 3
EN

Stack Overflow用户

发布于 2022-07-18 08:45:39

我注意到您正在服务中调用findOneBy,但是模拟了findOne存储库方法。

您必须模拟服务的findOne方法或存储库的findOneBy。在当前的方法中,您可以模拟存储库。此用例的解决方案如下所示:

代码语言:javascript
运行
复制
const mockUserRepositoryFactory = jest.fn(() => ({
  // Change here from findOne to findOneBy
  findOneBy: jest.fn(entity => entity),
}));

describe('JwtStrategy', () => {
  let jwtStrategy: JwtStrategy;
  let userService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [UserModule],
      providers: [
        JwtStrategy,
        UserService,            {
          provide: getRepositoryToken(UserEntity),
          useFactory: mockUserRepositoryFactory,
        },

      ]
    }).compile();

    jwtStrategy = await module.get<JwtStrategy>(JwtStrategy);
    userService = await module.get<UserService>(UserService);
  });

  describe('validate', () => {
    it('validates and returns user based on JWT payload', async () => {
      const user = new UserEntity();
      user.username = 'TestUser';

      // change findOne to findOneBy here as well
      userService.findOneBy.mockResolvedValue(user);
      const result = await jwtStrategy.validate({ username: 'TestUser' });
      expect(userService.findOneBy).toHaveBeenCalledWith({ username: 'TestUser' });
      expect(result).toEqual(user);
    });

    it('throws an unauthorized exception as user cannot be found', async () => {
      userService.findOneBy.mockResolvedValue(null);
      expect(jwtStrategy.validate({ username: 'TestUser' })).rejects.toThrow(UnauthorizedException);
    });
  });
});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73019162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档