Jest spyOn() 调用实际函数而不是模拟函数
Jest spyOn() calls the actual function instead of the mocked
我正在测试调用辅助函数 callApi
的 apiMiddleware
。为了防止调用将发出 API 调用的实际 callApi
,我模拟了该函数。但是,它仍然会被调用。
apiMiddleware.js
import axios from 'axios';
export const CALL_API = 'Call API';
export const callApi = (...arg) => {
return axios(...arg)
.then( /*handle success*/ )
.catch( /*handle error*/ );
};
export default store => next => action => {
// determine whether to execute this middleware
const callAPI = action[CALL_API];
if (typeof callAPI === 'undefined') {
return next(action)
}
return callAPI(...callAPI)
.then( /*handle success*/ )
.catch( /*handle error*/ );
}
apiMiddleware.spec.js
import * as apiMiddleware from './apiMiddleware';
const { CALL_API, default: middleware, callApi } = apiMiddleware;
describe('Api Middleware', () => {
const store = {getState: jest.fn()};
const next = jest.fn();
let action;
beforeEach(() => {
// clear the result of the previous calls
next.mockClear();
// action that trigger apiMiddleware
action = {
[CALL_API]: {
// list of properties that change from test to test
}
};
});
it('calls mocked version of `callApi', () => {
const callApi = jest.spyOn(apiMiddleware, 'callApi').mockReturnValue(Promise.resolve());
// error point: middleware() calls the actual `callApi()`
middleware(store)(next)(action);
// assertion
});
});
请忽略 callApi
函数的操作属性和参数。我不认为他们是我要表达的重点。
如果您需要进一步说明,请告诉我。
开玩笑的 mocking 只适用于导入的函数。在您的 apiMiddleware.js
中,default
函数正在调用 callApi
变量,而不是 "exported" callApi
函数。要使模拟工作,请将 callApi
移动到它自己的模块中,并将其 import
移动到 apiMiddleware.js
问得好!
我解决了将我的代码转换为 Class
的问题,示例:
// Implementation
export class Location {
getLocation() {
const environment = this.getEnvironmentVariable();
return environment === "1" ? "USA" : "GLOBAL";
}
getEnvironmentVariable() {
return process.env.REACT_APP_LOCATION;
}
}
// Test
import { Location } from "./config";
test('location', () => {
const config = new Location();
jest.spyOn(config, "getEnvironmentVariable").mockReturnValue("1")
const location = config.getLocation();
expect(location).toBe("USA");
});
我正在测试调用辅助函数 callApi
的 apiMiddleware
。为了防止调用将发出 API 调用的实际 callApi
,我模拟了该函数。但是,它仍然会被调用。
apiMiddleware.js
import axios from 'axios';
export const CALL_API = 'Call API';
export const callApi = (...arg) => {
return axios(...arg)
.then( /*handle success*/ )
.catch( /*handle error*/ );
};
export default store => next => action => {
// determine whether to execute this middleware
const callAPI = action[CALL_API];
if (typeof callAPI === 'undefined') {
return next(action)
}
return callAPI(...callAPI)
.then( /*handle success*/ )
.catch( /*handle error*/ );
}
apiMiddleware.spec.js
import * as apiMiddleware from './apiMiddleware';
const { CALL_API, default: middleware, callApi } = apiMiddleware;
describe('Api Middleware', () => {
const store = {getState: jest.fn()};
const next = jest.fn();
let action;
beforeEach(() => {
// clear the result of the previous calls
next.mockClear();
// action that trigger apiMiddleware
action = {
[CALL_API]: {
// list of properties that change from test to test
}
};
});
it('calls mocked version of `callApi', () => {
const callApi = jest.spyOn(apiMiddleware, 'callApi').mockReturnValue(Promise.resolve());
// error point: middleware() calls the actual `callApi()`
middleware(store)(next)(action);
// assertion
});
});
请忽略 callApi
函数的操作属性和参数。我不认为他们是我要表达的重点。
如果您需要进一步说明,请告诉我。
开玩笑的 mocking 只适用于导入的函数。在您的 apiMiddleware.js
中,default
函数正在调用 callApi
变量,而不是 "exported" callApi
函数。要使模拟工作,请将 callApi
移动到它自己的模块中,并将其 import
移动到 apiMiddleware.js
问得好!
我解决了将我的代码转换为 Class
的问题,示例:
// Implementation
export class Location {
getLocation() {
const environment = this.getEnvironmentVariable();
return environment === "1" ? "USA" : "GLOBAL";
}
getEnvironmentVariable() {
return process.env.REACT_APP_LOCATION;
}
}
// Test
import { Location } from "./config";
test('location', () => {
const config = new Location();
jest.spyOn(config, "getEnvironmentVariable").mockReturnValue("1")
const location = config.getLocation();
expect(location).toBe("USA");
});