应用集成测试时测试功能组合的正确方法是什么?
What could be the right way to test functions combined when applying Integration testing?
一个名为 "validateData" 的函数是单独测试的,为了简单起见,它只有 2 个测试,但是当我将这个函数组合到另一个函数中时,我发现自己在重复(几乎)相同的测试,例如:
src/controllers/user/createUser.js
export function validateData(data) {
if (!data) {
const err = new Error('data must be present');
err.code = 400;
throw err;
}
return data;
}
export async function createUser(data) {
validateData(data);
try {
const user = await UserModel.create(data);
return 'ok';
} catch(err) {
throw err;
}
}
export default createUser;
src/router/user/index.js
// Dependencies:
import { Router } from 'express';
import users from 'controllers/user/createUser';
import { methodNotAllowed } from 'utils/helpers';
// Helpers:
const router = Router();
router.route('/users')
.post((req, res) => {
createUser(req.body)
.then(summary => res.status(201).json({ message: "created" }))
.catch(err => res.status(400).json({ err: err.message }));
})
.all(methodNotAllowed(`Use solely POST method in this action.`));
test/controllers/user/createUser.test.js
import { should, expect } from 'chai';
import { validateData, createUser } from 'controllers/user/createUser';
describe('Controller', () => {
describe('#validateData', () => {
describe('when data is not send', () => {
it("should return error: 'data must be present'", () => {
(() => validateData(null))
.should.Throw("'data' must be present")
.with.property('code', 400);
});
});
describe('when data is sent', () => {
it("should return the same data input", () => {
const input = { firstName: 'Norman', lastName: 'etc' };
const output = validateData(input);
output.should.equal(input);
});
});
});
describe('#createUser', () => {
describe('when data is not send', () => {
it("should return error: 'data must be present'", async () => {
try {
await createUser(null)
} catch(err) {
err.should.include({
code: 400,
message: "data must be present"
});
}
});
});
describe('when data is sent', () => {
it("should return the same data input", async () => {
const input = { firstName: 'Norman', lastName: 'etc' };
const output = await createUser(input);
output.should.equal('ok');
});
});
});
});
因此,如果您看到我将相同的函数 "validateData" 重用到 "createUser" 函数中,那么它也会抛出与之前在“#validateData”描述块中测试过的错误相同的错误。
测试软件可以吗?
此外,我必须在 express 中重用这两个函数,因此 "validateData" 的测试将被测试 3 次。
1. #validateData, 2. #createUser and 3. #POST /users
我想知道这是否可以,因为对我来说似乎还可以,但测试变得混乱,因为我有许多功能组合在一起以获得所需的结果。
您希望避免多次测试函数 validateData 的内部结构。
如果您能够中断调用更改并将具体函数 validateData 替换为可以断言它已被调用的模拟,那么这应该足以验证是否调用了 validateData。
如果您能够用存根替换 validateData,即针对给定输入的预打包版本将 return 硬编码输出,那么您可以使用它来验证调用者在以下情况下是否正常运行validateData returns 是众所周知的输入的众所周知的值。
最后,如果您使用与上面的存根相同的输入验证 validateData,并期望得到相同的输出,那么您可以非常确定它在投入生产时会正常工作。至少对于您使用存根验证的案例以及后来的验证数据。
在很多地方重复相同的测试很麻烦,而且会造成维护负担。
一个名为 "validateData" 的函数是单独测试的,为了简单起见,它只有 2 个测试,但是当我将这个函数组合到另一个函数中时,我发现自己在重复(几乎)相同的测试,例如:
src/controllers/user/createUser.js
export function validateData(data) {
if (!data) {
const err = new Error('data must be present');
err.code = 400;
throw err;
}
return data;
}
export async function createUser(data) {
validateData(data);
try {
const user = await UserModel.create(data);
return 'ok';
} catch(err) {
throw err;
}
}
export default createUser;
src/router/user/index.js
// Dependencies:
import { Router } from 'express';
import users from 'controllers/user/createUser';
import { methodNotAllowed } from 'utils/helpers';
// Helpers:
const router = Router();
router.route('/users')
.post((req, res) => {
createUser(req.body)
.then(summary => res.status(201).json({ message: "created" }))
.catch(err => res.status(400).json({ err: err.message }));
})
.all(methodNotAllowed(`Use solely POST method in this action.`));
test/controllers/user/createUser.test.js
import { should, expect } from 'chai';
import { validateData, createUser } from 'controllers/user/createUser';
describe('Controller', () => {
describe('#validateData', () => {
describe('when data is not send', () => {
it("should return error: 'data must be present'", () => {
(() => validateData(null))
.should.Throw("'data' must be present")
.with.property('code', 400);
});
});
describe('when data is sent', () => {
it("should return the same data input", () => {
const input = { firstName: 'Norman', lastName: 'etc' };
const output = validateData(input);
output.should.equal(input);
});
});
});
describe('#createUser', () => {
describe('when data is not send', () => {
it("should return error: 'data must be present'", async () => {
try {
await createUser(null)
} catch(err) {
err.should.include({
code: 400,
message: "data must be present"
});
}
});
});
describe('when data is sent', () => {
it("should return the same data input", async () => {
const input = { firstName: 'Norman', lastName: 'etc' };
const output = await createUser(input);
output.should.equal('ok');
});
});
});
});
因此,如果您看到我将相同的函数 "validateData" 重用到 "createUser" 函数中,那么它也会抛出与之前在“#validateData”描述块中测试过的错误相同的错误。
测试软件可以吗?
此外,我必须在 express 中重用这两个函数,因此 "validateData" 的测试将被测试 3 次。
1. #validateData, 2. #createUser and 3. #POST /users
我想知道这是否可以,因为对我来说似乎还可以,但测试变得混乱,因为我有许多功能组合在一起以获得所需的结果。
您希望避免多次测试函数 validateData 的内部结构。
如果您能够中断调用更改并将具体函数 validateData 替换为可以断言它已被调用的模拟,那么这应该足以验证是否调用了 validateData。
如果您能够用存根替换 validateData,即针对给定输入的预打包版本将 return 硬编码输出,那么您可以使用它来验证调用者在以下情况下是否正常运行validateData returns 是众所周知的输入的众所周知的值。
最后,如果您使用与上面的存根相同的输入验证 validateData,并期望得到相同的输出,那么您可以非常确定它在投入生产时会正常工作。至少对于您使用存根验证的案例以及后来的验证数据。
在很多地方重复相同的测试很麻烦,而且会造成维护负担。