NestJS 模拟 returns Guard 的 Mixin
NestJS Mocking a Mixin that returns a Guard
我希望对我遇到的问题有一些了解。
我有一个生成守卫的混入。生成的守卫使用注入的服务。这是 mixin 的代码:
import {
CanActivate,
ExecutionContext,
Injectable,
mixin,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AccountService } from 'src/modules/account/account.service';
export const ForAccountGuard = (
paramName: string,
{ required = false }: { required?: boolean } = {}
) => {
@Injectable()
class _ForAccountGuard implements CanActivate {
constructor(private readonly accountService: AccountService) {}
async canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const accountId = ctx.getArgs()[paramName];
const currentUser = ctx.getContext().user;
if (required && !accountId) {
return false;
}
if (accountId) {
const account = await this.accountService.findUserAccount(
accountId,
currentUser.id
);
return !!account;
}
return true;
}
}
return mixin(_ForAccountGuard);
};
在我对使用此 mixin 作为保护的解析器的测试中,我正在执行以下操作:
@Query(() => [PropertyEntity])
@UseGuards(ForAccountGuard('accountId'))
async allProperties(@Args() { accountId }: AllPropertiesArgs) {
// <implementation removed>
}
所以,我 运行 遇到的问题是 运行 测试时出现以下错误:
Cannot find module 'src/modules/account/account.service' from 'modules/common/guards/for-account.guard.ts'
Require stack:
modules/common/guards/for-account.guard.ts
modules/property/property.resolver.spec.ts
注入的 AccountService 似乎没有被解析。
我不太确定如何告诉 Nest 的测试模块覆盖作为混入的守卫。我一直这样尝试,但似乎没有用:
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PropertyResolver,
...
],
})
.overrideGuard(ForAccountGuard)
.useValue(createMock<typeof ForAccountGuard>())
.compile();
);
});
那么,我应该如何模拟一个混入的守卫?
好吧,经过一番修修补补,我想出了一个解决办法。
放弃 overrideGuard
方法并直接 jest.mock
整个混合似乎可以解决问题。
所以,我创建了一个模拟:
import { CanActivate, Injectable, mixin } from '@nestjs/common';
export const mockForAccountGuard = () => {
@Injectable()
class _ForAccountGuardMock implements CanActivate {
canActivate() {
return true;
}
}
return mixin(_ForAccountGuardMock);
};
然后我用 jest.mock
来模拟它:
// in my test file
import { mockForAccountGuard } from '../common/guards/__mocks__/for-account.guard';
import { ForAccountGuard } from '../common/guards/for-account.guard';
jest.mock('../common/guards/for-account.guard', () => ({
ForAccountGuard: mockForAccountGuard,
}));
...
describe('PropertyResolver', () => {
...
beforeEach(() => {
...
const module: TestingModule = await Test.createTestingModule({
...
}).compile() // note, not using overrideGuards here
});
})
这似乎可以解决问题![=15=]
我希望对我遇到的问题有一些了解。
我有一个生成守卫的混入。生成的守卫使用注入的服务。这是 mixin 的代码:
import {
CanActivate,
ExecutionContext,
Injectable,
mixin,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AccountService } from 'src/modules/account/account.service';
export const ForAccountGuard = (
paramName: string,
{ required = false }: { required?: boolean } = {}
) => {
@Injectable()
class _ForAccountGuard implements CanActivate {
constructor(private readonly accountService: AccountService) {}
async canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const accountId = ctx.getArgs()[paramName];
const currentUser = ctx.getContext().user;
if (required && !accountId) {
return false;
}
if (accountId) {
const account = await this.accountService.findUserAccount(
accountId,
currentUser.id
);
return !!account;
}
return true;
}
}
return mixin(_ForAccountGuard);
};
在我对使用此 mixin 作为保护的解析器的测试中,我正在执行以下操作:
@Query(() => [PropertyEntity])
@UseGuards(ForAccountGuard('accountId'))
async allProperties(@Args() { accountId }: AllPropertiesArgs) {
// <implementation removed>
}
所以,我 运行 遇到的问题是 运行 测试时出现以下错误:
Cannot find module 'src/modules/account/account.service' from 'modules/common/guards/for-account.guard.ts'
Require stack:
modules/common/guards/for-account.guard.ts
modules/property/property.resolver.spec.ts
注入的 AccountService 似乎没有被解析。
我不太确定如何告诉 Nest 的测试模块覆盖作为混入的守卫。我一直这样尝试,但似乎没有用:
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PropertyResolver,
...
],
})
.overrideGuard(ForAccountGuard)
.useValue(createMock<typeof ForAccountGuard>())
.compile();
);
});
那么,我应该如何模拟一个混入的守卫?
好吧,经过一番修修补补,我想出了一个解决办法。
放弃 overrideGuard
方法并直接 jest.mock
整个混合似乎可以解决问题。
所以,我创建了一个模拟:
import { CanActivate, Injectable, mixin } from '@nestjs/common';
export const mockForAccountGuard = () => {
@Injectable()
class _ForAccountGuardMock implements CanActivate {
canActivate() {
return true;
}
}
return mixin(_ForAccountGuardMock);
};
然后我用 jest.mock
来模拟它:
// in my test file
import { mockForAccountGuard } from '../common/guards/__mocks__/for-account.guard';
import { ForAccountGuard } from '../common/guards/for-account.guard';
jest.mock('../common/guards/for-account.guard', () => ({
ForAccountGuard: mockForAccountGuard,
}));
...
describe('PropertyResolver', () => {
...
beforeEach(() => {
...
const module: TestingModule = await Test.createTestingModule({
...
}).compile() // note, not using overrideGuards here
});
})
这似乎可以解决问题![=15=]