我正在为一个实现用户CRUD的快递应用编写测试。在编写集成测试之前,我做了一个工厂,可以为测试创建用户。
factories.js
import faker from 'faker';
import { factory } from 'factory-girl';
import User from '../../src/app/models/User';
factory.define('User', User, {
name: faker.name.firstName(),
email: faker.internet.email(),
password: faker.internet.password(),
admin: false,
});
export default factory;
很好 现在,每当我需要为测试创建一个用户时,我只需要使用 factory.create()
对吗?错了。在一个测试套件中,我需要两个用户,一个是管理员,另一个不是。所以我写了这个setupteardown。
let user, admin;
const createUsers = async () => {
// Runs ok
user = await factory.create('User');
// Error
admin = await factory.create('User', { admin: true });
};
const removeUsers = async () => {
await user.remove();
await admin.remove();
};
beforeAll(async () => {
await createUsers();
});
afterAll(async () => {
await removeUsers();
mongoose.connection.close();
});
user = await factory.create(...)
运行正常,但是 admin = await factory.create(...)
提出了 MongoError: E11000 duplicate key error collection
.
这是因为工厂试图用一个已经在使用的电子邮件来创建一个用户(电子邮件对于模型用户来说是唯一的)。我可以通过向创建方法传递一个特定的电子邮件来确保这种情况不会发生,就像我传递 admin: true
,但这就没有什么意义了,因为我创建工厂就是为了避免这种麻烦。
你们能不能指出我在这里做错了什么?我想这和我定义工厂的方式有关。先谢谢你们了。
EDIT: 正如建议的那样,我通过使用以下方法解决了这个问题 factory.sequence
.
factory.define('User', User, {
name: factory.sequence('User.name', () => faker.name.firstName()),
lastName: factory.sequence('User.lastName', () => faker.name.lastName()),
email: factory.sequence('User.email', () => faker.internet.email()),
password: factory.sequence('User.password', () => faker.internet.password()),
redefinePassword: false,
admin: false,
});
虽然faker.internet.email()每次被调用时都会创建一个新的假邮件,但在为工厂定义模板对象时,你只需要调用它一次。研究一下factory.sequence API,可以让工厂为每个被创建的对象运行一些代码。https:/www.npmjs.compackagefactory-girl#defining-factories
或者干脆把函数faker.internet.email传过来,不加(),我想厂妹每次也会调用这个函数,你也可以让你的define调用取一个返回这个对象的函数(调用faker.internet.email()后),这么多选择!