Merged PR 327: テストを最新化(ユーザー追加)
## 概要 [Task2400: テストを最新化(ユーザー追加)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2400) - 新規ユーザー追加のユニットテストをDBを利用するテストへ置き換え - API呼び出しやRepository呼び出しをMockする仕組みを改善 - オブジェクト全てを上書きするのではなく、特定のメソッドのみを上書きする形に修正 - これにより、他のDBアクセスは正常にSQLiteへのアクセスが成功しつつ、特定のDBアクセスのみMockにできる ## レビューポイント - テストケースは足りているか - Mockする仕組みを改善したが、修正内容は問題ないか ## 動作確認状況 - npm run test で成功
This commit is contained in:
parent
86d11e7447
commit
704a5aafc2
@ -1,4 +1,7 @@
|
||||
import { ConflictError } from '../../gateways/adb2c/adb2c.service';
|
||||
import { User, newUser } from '../../repositories/users/entity/user.entity';
|
||||
|
||||
// ### ユニットテスト用コード以外では絶対に使用してはいけないダーティな手段を使用しているが、他の箇所では使用しないこと ###
|
||||
|
||||
/**
|
||||
* adB2cServiceのモックを作成して、TServiceが依存するサービス(adB2cService)の参照を上書きする
|
||||
@ -17,11 +20,14 @@ export const overrideAdB2cService = <TService>(
|
||||
},
|
||||
): void => {
|
||||
const { createUser } = overrides;
|
||||
Object.defineProperty(service, 'adB2cService', {
|
||||
value: {
|
||||
createUser: createUser ?? jest.fn().mockResolvedValue({ sub: 'dummy' }),
|
||||
},
|
||||
});
|
||||
// テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得
|
||||
const obj = (service as any).adB2cService;
|
||||
if (createUser) {
|
||||
Object.defineProperty(obj, createUser.name, {
|
||||
value: createUser,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -38,6 +44,11 @@ export const overrideSendgridService = <TService>(
|
||||
userId: number,
|
||||
email: string,
|
||||
) => Promise<{ subject: string; text: string; html: string }>;
|
||||
createMailContentFromEmailConfirmForNormalUser?: (
|
||||
accountId: number,
|
||||
userId: number,
|
||||
email: string,
|
||||
) => Promise<{ subject: string; text: string; html: string }>;
|
||||
sendMail?: (
|
||||
to: string,
|
||||
from: string,
|
||||
@ -47,17 +58,59 @@ export const overrideSendgridService = <TService>(
|
||||
) => Promise<void>;
|
||||
},
|
||||
): void => {
|
||||
const { createMailContentFromEmailConfirm, sendMail } = overrides;
|
||||
Object.defineProperty(service, 'sendgridService', {
|
||||
value: {
|
||||
createMailContentFromEmailConfirm:
|
||||
createMailContentFromEmailConfirm ??
|
||||
jest.fn().mockResolvedValue({
|
||||
subject: 'dummySubject',
|
||||
text: 'dummyText',
|
||||
html: 'dummyHtml',
|
||||
}),
|
||||
sendMail: sendMail ?? jest.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
});
|
||||
const {
|
||||
createMailContentFromEmailConfirm,
|
||||
createMailContentFromEmailConfirmForNormalUser,
|
||||
sendMail,
|
||||
} = overrides;
|
||||
|
||||
// テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得
|
||||
const obj = (service as any).sendgridService;
|
||||
if (sendMail) {
|
||||
Object.defineProperty(obj, sendMail.name, {
|
||||
value: sendMail,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (createMailContentFromEmailConfirm) {
|
||||
Object.defineProperty(obj, createMailContentFromEmailConfirm.name, {
|
||||
value: createMailContentFromEmailConfirm,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (createMailContentFromEmailConfirmForNormalUser) {
|
||||
Object.defineProperty(
|
||||
obj,
|
||||
createMailContentFromEmailConfirmForNormalUser.name,
|
||||
{
|
||||
value: createMailContentFromEmailConfirmForNormalUser,
|
||||
writable: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* usersRepositoryのモックを作成して、TServiceが依存するサービス(usersRepositoryService)の参照を上書きする
|
||||
* ※ serviceに指定するオブジェクトは`usersRepository: UsersRepositoryService`メンバ変数を持つ必要がある
|
||||
* @param service 上書きしたいTService
|
||||
* @param overrides usersRepositoryの各種メソッドのモックが返す値(省略した場合は既定のダミーの値)
|
||||
*/
|
||||
export const overrideUsersRepositoryService = <TService>(
|
||||
service: TService,
|
||||
overrides: {
|
||||
createNormalUser?: (user: newUser) => Promise<User>;
|
||||
},
|
||||
): void => {
|
||||
const { createNormalUser } = overrides;
|
||||
// テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得
|
||||
const obj = (service as any).usersRepository;
|
||||
if (createNormalUser) {
|
||||
Object.defineProperty(obj, createNormalUser.name, {
|
||||
value: createNormalUser,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,7 +137,7 @@ describe('createAccount', () => {
|
||||
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||||
} else {
|
||||
expect(true).toBe(false); // ここには来てはいけない
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ describe('createAccount', () => {
|
||||
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E010301'));
|
||||
} else {
|
||||
expect(true).toBe(false); // ここには来てはいけない
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,69 @@ import { AdB2cMockValue, makeAdB2cServiceMock } from './users.service.mock';
|
||||
import { AdB2cService } from '../../../gateways/adb2c/adb2c.service';
|
||||
import { LICENSE_ALLOCATED_STATUS, LICENSE_TYPE } from '../../../constants';
|
||||
|
||||
export const createAccountAndAdminUser = async (
|
||||
datasource: DataSource,
|
||||
adminExternalId: string,
|
||||
): Promise<{
|
||||
accountId: number;
|
||||
adminId: number;
|
||||
role: string;
|
||||
tier: number;
|
||||
}> => {
|
||||
const { identifiers: account_idf } = await datasource
|
||||
.getRepository(Account)
|
||||
.insert({
|
||||
tier: 1,
|
||||
country: 'JP',
|
||||
delegation_permission: false,
|
||||
locked: false,
|
||||
company_name: 'test inc.',
|
||||
verified: true,
|
||||
deleted_at: '',
|
||||
created_by: 'test_runner',
|
||||
created_at: new Date(),
|
||||
updated_by: 'updater',
|
||||
updated_at: new Date(),
|
||||
});
|
||||
const account = account_idf.pop() as Account;
|
||||
|
||||
const { identifiers: user_idf } = await datasource
|
||||
.getRepository(User)
|
||||
.insert({
|
||||
account_id: account.id,
|
||||
external_id: adminExternalId,
|
||||
role: 'admin none',
|
||||
accepted_terms_version: '1.0',
|
||||
email_verified: true,
|
||||
auto_renew: true,
|
||||
license_alert: true,
|
||||
notification: true,
|
||||
encryption: true,
|
||||
encryption_password: 'password',
|
||||
prompt: true,
|
||||
created_by: 'test_runner',
|
||||
created_at: new Date(),
|
||||
updated_by: 'updater',
|
||||
updated_at: new Date(),
|
||||
});
|
||||
const user = user_idf.pop() as User;
|
||||
|
||||
// Accountの管理者を設定する
|
||||
await datasource.getRepository(Account).update(
|
||||
{ id: user.account_id },
|
||||
{
|
||||
primary_admin_user_id: user.id,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
accountId: account.id,
|
||||
adminId: user.id,
|
||||
role: user.role,
|
||||
tier: account.tier,
|
||||
};
|
||||
};
|
||||
|
||||
export const createAccount = async (
|
||||
datasource: DataSource,
|
||||
): Promise<{ accountId: number }> => {
|
||||
@ -116,6 +179,33 @@ export const getLicenses = async (
|
||||
return licenses;
|
||||
};
|
||||
|
||||
/**
|
||||
* テスト ユーティリティ: 指定外部IDを持つユーザーを取得する
|
||||
* @param dataSource データソース
|
||||
* @param externalId 外部ID
|
||||
* @returns 該当ユーザー
|
||||
*/
|
||||
export const getUserByExternalId = async (
|
||||
datasource: DataSource,
|
||||
externalId: string,
|
||||
): Promise<User> => {
|
||||
const user = await datasource.getRepository(User).findOne({
|
||||
where: {
|
||||
external_id: externalId,
|
||||
},
|
||||
});
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
* テスト ユーティリティ: すべてのユーザーを取得する
|
||||
* @param dataSource データソース
|
||||
* @returns 該当ユーザー一覧
|
||||
*/
|
||||
export const getUsers = async (dataSource: DataSource): Promise<User[]> => {
|
||||
return await dataSource.getRepository(User).find();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param datasource
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -45,13 +45,13 @@ export class User {
|
||||
@Column({ default: true })
|
||||
notification: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ default: false })
|
||||
encryption?: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
encryption_password?: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ default: false })
|
||||
prompt?: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user