我试图在一个没有单元测试的现有项目中引入一个小的更改,并决定尝试学习足够的nodejs和jest知识,以便在更改中包含测试。然而,我无法让mock像我期望的那样在python中工作。该项目使用godaddy的“kubernetes-client”库,并尝试从envvar“KUBECONFIG”创建一个config对象,如下所示:
// a few lines into server.js
// Instantiate Kubernetes client
const Client = require('kubernetes-client').Client
const config = require('kubernetes-client').config;
if (process.env.KUBECONFIG) {
client = new Client({
config: config.fromKubeconfig(config.loadKubeconfig(process.env.KUBECONFIG)),
version: '1.13'
});
}
else {
client = new Client({ config: config.getInCluster(), version: '1.9' });
}
字符串
在我的测试环境中,我不希望任何API调用,所以我尝试模拟它:
// __tests__/server.test.js
// Set up mocks at the top because of how server.js sets up k8s client
const k8sClient = require('kubernetes-client');
const narp = 'narp';
jest.mock('kubernetes-client', () => {
const noConfigmaps = jest.fn(() => {
throw narp;
});
const namespaces = jest.fn().mockReturnValue({
configmaps: jest.fn().mockReturnValue({
get: noConfigmaps
})
});
const addCustomResourceDefinition = jest.fn().mockReturnThis()
const mockClient = {
api: {
v1: {
namespaces
}
},
addCustomResourceDefinition: jest.fn().mockReturnThis(),
};
return {
Client: jest.fn(() => mockClient),
config: {
fromKubeconfig: jest.fn().mockReturnThis(),
loadKubeconfig: jest.fn().mockReturnThis(),
getInCluster: jest.fn().mockReturnThis()
},
};
});
const app = require('../server.js')
const supertest = require('supertest');
const requestWithSuperTest = supertest(app.app);
describe('Testing server.js', () => {
afterAll(() => {
app.server.close();
});
describe('Tests with k8s client throwing error when fetching configmaps', () => {
it("finds a resource's ingressGroup by name", () => {
var resource = {
"spec": {
"ingressClass": "foo",
"ingressTargetDNSName": "foo"
}
};
var ingressGroups = [
{
"ingressClass": "bar",
"hostName": "bar",
"name": "barName"
},
{
"ingressClass": "foo",
"hostName": "foo",
"name": "fooName"
}
];
expect(app.findMatchingIngressGroupForResource(resource, ingressGroups)).toBe("fooName");
});
it('GET /healthcheck should respond "Healthy"', async () => {
const resp = await requestWithSuperTest.get('/healthcheck');
console.log("Response in Testing Endpoints: " + JSON.stringify(resp));
expect(resp.status).toEqual(200);
expect(resp.type).toEqual(expect.stringContaining('text'));
expect(resp.text).toEqual('Healthy');
});
it('Tests getIngressGroups() rejects with error when it cannot get configmaps', async () => {
app.getIngressGroups()
.then()
.catch(error => {
expect(error).toEqual("Failed to fetch Ingress Groups: " + narp);
});
});
});
});
型
通过这种设置,测试通过了(尽管我怀疑这是没有意义的)。如果我尝试使用beforeEach
函数(或不使用)将mock移动到describe
或it
块中,以便我可以更改行为以返回mock数据而不是抛出错误,我会立即收到k8s客户端的错误,抱怨它找不到我的kubeconfig/clusterconfig:
$ npm run testj
> testj
> jest --detectOpenHandles
kubernetes-client deprecated require('kubernetes-client').config, use require('kubernetes-client/backends/request').config. server.js:45:44
kubernetes-client deprecated loadKubeconfig see https://github.com/godaddy/kubernetes-client/blob/master/merging-with-kubernetes.md#request-kubeconfig- server.js:49:42
FAIL __tests__/server.test.js
● Test suite failed to run
ENOENT: no such file or directory, open 'NOT_A_FILE'
44 | if (process.env.KUBECONFIG) {
45 | client = new Client({
> 46 | config: config.fromKubeconfig(config.loadKubeconfig(process.env.KUBECONFIG)),
| ^
47 | version: '1.13'
48 | });
49 | }
at node_modules/kubernetes-client/backends/request/config.js:335:37
at Array.map (<anonymous>)
at Object.loadKubeconfig (node_modules/kubernetes-client/backends/request/config.js:334:28)
at Object.eval [as loadKubeconfig] (eval at wrapfunction (node_modules/kubernetes-client/node_modules/depd/index.js:425:22), <anonymous>:5:11)
at Object.<anonymous> (server.js:46:46)
型
如果任何人遇到这种行为之前或看到一些明显错误的线路,我真的很感激任何提示或信息。谢谢!
1条答案
按热度按时间sqxo8psd1#
我不得不改变一些东西来让它工作:
jest.doMock()
而不是jest.mock()
describe
块内的let app
而不是const app
beforeEach()
调用jest.resetModules()
afterEach()
,它调用app.close()
it
块中,在覆盖之前显式调用jest.resetModules()
it
块中,调用app.close()
并在调用实际的function-under-test/expect之前重新初始化app
生成的测试文件:
字符串