У меня есть модуль с именем authProvider. js, который я хочу смоделировать при тестировании одной из моих функций в API. js. Я установил "automock": true в моей конфигурации jest.
Это моя структура
src
|-auth
| |-__mocks__
| | |-authProvider.js
| |-authProvider.js
|-utils
|-api.js
|-api.test.js
Это то, что я пробовал до сих пор, но только с успехом с первым тестом. Я не уверен, как настроить насмешку во втором тестовом примере ...
api.test. js
import { mockAuthProvider } from "../auth/__mocks__/authProvider";
import { getDefaultHeaders, getValueIndexByColumnName } from './api';
describe('API utils', () => {
describe('getDefaultHeaders', () => {
it('Not authenticated', async () => {
expect(await getDefaultHeaders()).toEqual({
'Content-Type': 'application/json'
});
});
it('Authenticated', async () => {
mockAuthProvider.getAccount.mockImplementationOnce(() =>
Promise.resolve({user: 'test'})
);
const headers = await getDefaultHeaders();
expect(mockAuthProvider.getAccount).toBeCalled();
expect(headers).toEqual({
Authorization: 'Bearer abc123',
'Content-Type': 'application/json'
});
});
});
});
api. js
import { authProvider } from '../auth/authProvider';
import settings from '../settings';
export async function getDefaultHeaders() {
const account = await authProvider.getAccount();
const authenticationParameters = {
scopes: ['api://' + settings.AD_CLIENT_ID + '/login'],
redirectUri: window.location.origin + '/auth.html'
};
let token;
if (account) {
try {
token = await authProvider.acquireTokenSilent(authenticationParameters);
} catch (error) {
token = await authProvider.acquireTokenPopup(authenticationParameters);
}
}
if (token) {
return {
Authorization: `Bearer ${token.accessToken}`,
'Content-Type': 'application/json'
}
}
return {
'Content-Type': 'application/json'
}
}
__ mocks __ / authProvider. js
const mockAuthProvider = {
getAccount: jest.fn(),
acquireTokenSilent: jest.fn(),
acquireTokenPopup: jest.fn()
};
module.exports = {
mockAuthProvider
};
Сообщение об ошибке
Expected number of calls: >= 1
Received number of calls: 0
18 | const headers = await getDefaultHeaders();
19 |
> 20 | expect(mockAuthProvider.getAccount).toBeCalled();
| ^
ОБНОВЛЕНИЕ
Я добавил файл, чтобы смоделировать весь модуль, который экспортирует провайдера аутентификации, но все еще не лучший способ решить его, я думаю. У меня возникают трудности с использованием его в нескольких тестовых случаях, поскольку мне нужно указать возвращаемые значения в указанном порядке c.
Есть ли лучший способ решить эту проблему?
__ mocks __ / response-aad-msal. js
import React from 'react';
const errorObj = {
message: 'Some error'
};
export const mockGetAccount = jest.fn()
.mockReturnValueOnce(null) // Not authenticated
.mockReturnValueOnce({user: 'test'}) // Authenticated silent
.mockReturnValueOnce({user: 'test'}); // Authenticated popup
export const mockAcquireTokenSilent = jest.fn()
.mockReturnValueOnce({accessToken: 'abc123'}) // Authenticated silent
.mockRejectedValueOnce(errorObj); // Authenticated popup
export const mockAcquireTokenPopup = jest.fn()
.mockReturnValueOnce({accessToken: 'abc123'}); // Authenticated popup
export const MsalAuthProvider = jest.fn(() => ({
getAccount: mockGetAccount,
acquireTokenSilent: mockAcquireTokenSilent,
acquireTokenPopup: mockAcquireTokenPopup
}));
export const AuthenticationState = {
Authenticated: 'Authenticated',
Unauthenticated: 'Unauthenticated'
};
export const LoginType = {
Popup: 'popup'
};
export const AuthenticationActions = {
Initializing: 'Initializing',
Initialized: 'Initialized',
AcquiredIdTokenSuccess: 'AcquiredIdTokenSuccess',
AcquiredAccessTokenSuccess: 'AcquiredAccessTokenSuccess',
AcquiredAccessTokenError: 'AcquiredAccessTokenError',
LoginSuccess: 'LoginSuccess',
LoginError: 'LoginError',
AcquiredIdTokenError: 'AcquiredIdTokenError',
LogoutSucc: 'LogoutSucc',
AuthenticatedStateChanged: 'AuthenticatedStateChanged'
};
export const AzureAD = ({children}) => <div>{children}</div>;
Новый api.test. js выглядит следующим образом, обратите внимание, что порядок тестов теперь важен, поскольку возвращаемые значения из макеты в фиксированном порядке.
import { getDefaultHeaders, axiosCreate, getValueIndexByColumnName } from './api';
describe('API utils', () => {
describe('getDefaultHeaders', () => {
it('Not authenticated', async () => {
const headers = await getDefaultHeaders();
expect(headers).toEqual({
'Content-Type': 'application/json'
});
});
it('Authenticated silent', async () => {
const headers = await getDefaultHeaders();
expect(headers).toEqual({
Authorization: 'Bearer abc123',
'Content-Type': 'application/json'
});
});
it('Authenticated popup', async () => {
const headers = await getDefaultHeaders();
expect(headers).toEqual({
Authorization: 'Bearer abc123',
'Content-Type': 'application/json'
});
});
});
describe('axiosCreate', () => {
it('Create axios API base', () => {
expect(axiosCreate()).toBeTruthy();
});
});
describe('getValueIndexByColumnName', () => {
it('Invalid input data', () => {
expect(getValueIndexByColumnName([], null)).toEqual(null);
expect(getValueIndexByColumnName(['column1'], null)).toEqual(-1);
});
it('Valid input data', () => {
expect(getValueIndexByColumnName(['column1'], 'column')).toEqual(-1);
expect(getValueIndexByColumnName(['column1'], 'column1')).toEqual(0);
expect(getValueIndexByColumnName(['column1', 'column2', 'column3'], 'column2')).toEqual(1);
});
});
});