Вопрос или проблема
Я пытаюсь написать модульные тесты для функции Cloud Firestore под названием setBrakeModeV2 с использованием Jest. Функция предназначена для установки режима торможения пользователя в true и обновления его пользовательских утверждений в Firebase Authentication. Вот фрагмент теста, который я написал:
it('должен установить режим торможения для пользователя в true', async () => {
const result = await setBrakeModeV2();
expect(result).toBe(true);
// и пользовательские утверждения должны быть обновлены
expect(admin.auth().setCustomUserClaims).toHaveBeenCalledWith('testUid', { brakeMode: true });
});
Однако я не уверен, как правильно смоделировать параметры req (запрос) и res (ответ), которые необходимо передать функции setBrakeModeV2. Поскольку это функция Cloud Firestore, эти параметры важны для правильного тестирования ее поведения.
Как мне замокировать объекты req и res для функции Cloud в Jest? Если это поможет, я могу предоставить детали реализации setBrakeModeV2, но моя текущая проблема заключается в передаче стандартных аргументов.
export const setBrakeModeV2 = onCall(
{
// Примечание: ⚙️⚙️⚙️ Дополнительная информация об этом объекте в интерфейсе HttpsOptions. ⚙️⚙️⚙️
maxInstances: 1,
memory: '256MiB',
// enforceAppCheck: true,
},
async (request: CallableRequest<null>) => {
consoleLogFn('setBrakeModeV2');
// 🪪 Проверка безопасности
const requestAuth = request?.auth;
verifyExistingUserPermissions(requestAuth);
const uid = requestAuth?.uid;
// Пользовательские утверждения
const tokenData = requestAuth?.token;
const userType = tokenData?.userType;
const stripeRole = tokenData?.stripeRole;
console.log('uid ===>', uid);
console.log('tokenData ===>', tokenData);
console.log('userType из токена ===>', userType);
console.log('stripeRole из токена ===>', stripeRole);
/**
* Эта функция позволяет пользователю, чья подписка на премиум истекла, продлить период истечения удаления аккаунта
* путем включения "режима торможения". Режим торможения можно включить только в том случае, если роль пользователя в Stripe равна null, что указывает на то, что
* пользователь больше не является активным премиум-подписчиком.
*
* Null-роль в Stripe подразумевает, что у пользователя была как минимум одна премиум-подписка в прошлом, но в настоящее время он не
* имеет активной премиум-подписки. Для получения дополнительной информации ознакомьтесь с документацией по жизненному циклу ролей Stripe.
*/
if (uid && userType && tokenData && stripeRole === null) {
const currentBreakModeValue = tokenData?.brakeMode;
await Promise.all([
admin
.auth()
/**
* в качестве альтернативы мы можем использовать .getUserByEmail(tokenData.email)
*/
.getUser(uid)
.then((user) => {
/*
* Обновить пользовательские утверждения
*/
const newCustomClaims: CustomClaim = {
// Скопировать существующие пользовательские утверждения
...(user.customClaims as CustomClaim),
// Изменить режим торможения на противоположный текущему значению
brakeMode: !currentBreakModeValue,
};
admin.auth().setCustomUserClaims(user.uid, newCustomClaims);
}),
]);
// Вернуть новое значение режима торможения клиенту
return !currentBreakModeValue;
}
return null;
}
);
Ответ или решение
Как протестировать Cloud Function setBrakeModeV2 с помощью Jest
Проверка функций облачных функций с использованием Jest — это важный шаг для обеспечения их надежности и корректного поведения. В вашем случае, вы хотите протестировать функцию setBrakeModeV2
, которая устанавливает режим торможения пользователя и обновляет его индивидуальные полномочия в Firebase Authentication. Давайте пройдемся по каждому шагу, чтобы настроить тестирование правильно.
1. Создание мока для объектов req
и res
Объект req
Объект req
(request) для облачных функций Firebase часто содержит информацию об аутентификации и дополнительных данных, отправляемых вместе с запросом. Вам нужно смоделировать его так, чтобы он содержал необходимые поля.
const req = {
auth: {
uid: 'testUid',
token: {
userType: 'testUserType',
stripeRole: null,
brakeMode: false,
},
},
};
Объект res
Объект res
(response) обычно не используется в вызовах onCall
, поскольку результат возвращается клиенту напрямую. Однако, если ваша функция использует его, вы можете смоделировать его следующим образом:
const res = {
send: jest.fn(),
};
2. Написание теста
Теперь, когда вы создали моки для req
и res
, вы можете написать тест для вашей функции. В тесте вы должны вызывать setBrakeModeV2
, передавая ему подготовленный объект req
, и ожидать, что функция выполнит обновление служебных полномочий.
import { setBrakeModeV2 } from './yourFunctionFile'; // Импортируйте вашу функцию
import admin from 'firebase-admin'; // Импортируйте admin, чтобы замокировать вызовы
jest.mock('firebase-admin'); // Мокирование firebase-admin
describe('setBrakeModeV2 Tests', () => {
beforeEach(() => {
jest.clearAllMocks(); // Очистка всех моков перед каждым тестом
});
it('должен установить режим торможения для пользователя в true', async () => {
const req = {
auth: {
uid: 'testUid',
token: {
userType: 'testUserType',
stripeRole: null,
brakeMode: false,
},
},
};
// Мокаем admin.auth().getUser
const mockUser = {
customClaims: { brakeMode: false },
uid: 'testUid',
};
admin.auth().getUser.mockResolvedValue(mockUser);
const result = await setBrakeModeV2(req);
expect(result).toBe(true);
expect(admin.auth().setCustomUserClaims).toHaveBeenCalledWith('testUid', { brakeMode: true });
});
it('должен вернуть null, если uid или userType отсутствуют', async () => {
const req = {};
const result = await setBrakeModeV2(req);
expect(result).toBeNull();
});
});
3. Объяснение тестов
-
Тест на успешное выполнение: В первом тесте вы передаете корректные данные для аутентификации и мока для
admin.auth().getUser
. После выполнения функцииsetBrakeModeV2
ожидается, что режим торможения устанавливается вtrue
, иsetCustomUserClaims
будет вызван с правильными аргументами. -
Тест на ошибочные данные: Во втором тесте вы передаете пустой объект
req
, проверяя, корректно ли функция возвращаетnull
, если у запроса отсутствуютuid
илиuserType
.
Заключение
Следуя этим шагам, вы сможете правильно протестировать вашу функцию setBrakeModeV2
с помощью Jest, удостоверившись, что ваша функция будет вести себя корректно в различных сценариях. Эффективное тестирование поможет улучшить качество кода и уменьшить количество ошибок в продакшен среде. Для получения дополнительной информации о Jest и мокировании объектов, ознакомьтесь с документацией Jest.