-
-
Notifications
You must be signed in to change notification settings - Fork 378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NEW TEST] Sequelize transactions #1985
Labels
enhancement
New feature or request
Comments
Is this solution correct?
@Injectable()
export class UsersService {
constructor(
private readonly sequelize: Sequelize,
@InjectModel(User)
private readonly userModel: typeof User,
@Inject(IORedisKey) private readonly redisClient: Redis,
) {}
// ......
async getUserModel(id: number): Promise<User> {
return this.userModel.findOne({
attributes: { exclude: ['pwd'] },
where: { id },
});
}
async findByAccount(account: string): Promise<User.UserInfo | null> {
const trans = await this.sequelize.transaction();
const user = await this.userModel.findOne({
where: {
account,
},
transaction: trans,
});
if (!user) return null;
const role = await user.$get('role', { transaction: trans });
const permissions = (
await role.$get('permissions', { transaction: trans })
).map(({ id, name, desc }) => ({
id,
name,
desc,
}));
await trans.commit();
const { id: roleId, name: roleName, desc: roleDesc } = role;
return {
...user.toJSON(),
roleId,
roleName,
roleDesc,
permissions,
};
}
// ......
}
import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/sequelize';
import { UsersService } from './users.service';
import { User as UserModel } from './models/user.model';
import { IORedisKey } from 'src/common/redis/redis.module';
import type { Redis } from 'ioredis';
import { Sequelize } from 'sequelize-typescript';
const testUser = {
id: 10007,
account: '176******',
avatar: 'avatar.png',
email: '[email protected]',
regisTime: '2023-01-28 12:16:06',
updateTime: '2023-01-29 14:01:35',
};
const testRole = {
id: 5,
name: 'admin',
desc: '管理员',
};
const testPermissions = {
id: 1,
name: 'userDel',
desc: 'Delete user',
};
describe('UsersService', () => {
let service: UsersService,
model: typeof UserModel,
redisClient: Redis,
sequelize: Sequelize;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: Sequelize,
useValue: {
transaction: jest.fn(),
},
},
{
provide: getModelToken(UserModel),
useValue: {
findOne: jest.fn(),
create: jest.fn(() => testUser),
},
},
{ provide: IORedisKey, useValue: {} },
],
}).compile();
service = module.get<UsersService>(UsersService);
model = module.get<typeof UserModel>(getModelToken(UserModel));
redisClient = module.get<Redis>(IORedisKey);
sequelize = module.get<Sequelize>(Sequelize);
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should get a single user by the method named getUserModel', () => {
const findSpy = jest.spyOn(model, 'findOne');
expect(service.getUserModel(10007));
expect(findSpy).toBeCalledWith({
attributes: { exclude: ['pwd'] },
where: { id: 10007 },
});
});
test('the method named findByAccount', async () => {
// mock transaction
const commit = jest.fn();
const transaction = jest.fn(async () => ({ commit }) as any);
const transSpy = jest
.spyOn(sequelize, 'transaction')
.mockImplementation(transaction);
const permissionsStub = jest.fn(() => ({
map: jest.fn(() => [testPermissions]),
})),
roleStub = jest.fn((key: string) => ({
...testRole,
$get: permissionsStub,
}));
const findSpy = jest.spyOn(model, 'findOne').mockReturnValue({
$get: roleStub,
toJSON: jest.fn(() => testUser),
} as any);
const retVal = await service.findByAccount('176********');
expect(transSpy).toBeCalledTimes(1);
expect(findSpy).toBeCalledWith({
where: { account: '176********' },
transaction: await transaction(),
});
expect(commit).toBeCalledTimes(1);
const { id: roleId, name: roleName, desc: roleDesc } = testRole;
expect(retVal).toEqual({
...testUser,
roleId,
roleName,
roleDesc,
permissions: [testPermissions],
});
});
}); ![]() These codes look kind of stupid ...... Can anyone suggest the correct solution (or any idea). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there an existing issue for this?
Feature Test To Be Requested
The sequelize-sample is really awesome, but we're using Sequelize Transactions in our codebase and by doing so we have to mock the Sequelize
transaction()
method or Nest will throw dependency errors:I've looked through the NestJS documentation and Discord but I couldn't find any good examples of how to do this because if I mock the Sequelize transaction like this, I don't get the value from my service call:
The Nest docs state to use a helper factory class but I couldn't find a good example of this either.
The text was updated successfully, but these errors were encountered: