Я создаю серию маршрутов для создания своего рода викторины. Я решил построить его почти как связанный список с каждым элементом в форме, указывающим на элементы next / prev. Я хочу, чтобы у всех были тесты, но я не могу понять, как написать тест для следующего:
async create(next){
// check if form already has elements added to it
const elements = await db.elements.findAll({ where: { form_id: this.formId } });
// if form already has elements added and next is not provided, append element to the end of the form
if (elements.length && !next) {
await this._createAtEnd(elements, next);
}
// if next is not the end of the element list, insert element before next element
else if (elements.length){
await this._insert(elements, next);
}
return db.elements.findAll({ where: { form_id: this.formId } });
}
async _insert(elements, next){
const tempPrevious = elements.filter(el => el.next_element_id === next).pop();
const tempNext = tempPrevious ? elements.filter(el => el.id === tempPrevious.next_element_id).pop() : null;
const created = await db.elements.create({
form_id: this.formId,
previous_element_id: tempPrevious ? tempPrevious.id : null,
next_element_id: next,
});
// update the element prior to the newly inserted element
if (tempPrevious) {
return Promise.all( [
tempPrevious.update({ next_element_id: created.id }),
tempNext.update({ previous_element_id: created.id }),
]);
}
// element is being inserted at the beginning
const first = elements.map(el => el.previous_element_id === null).pop();
return first.update({ previous_element_id: created.id });
}
Допустим, я заглушил базу данных (db
), чтобы тест выглядел следующим образом следующее:
it('should create a new element', async () => {
const formId = 1;
const next = 2;
const data = [
{ id: 0, form_id: formId, previous_element_id: null, next_element_id: 1, },
{ id: 1, form_id: formId, previous_element_id: 0, next_element_id: 2, },
{ id: 2, form_id: formId, previous_element_id: 1, next_element_id: null, },
];
data.forEach(el => el.update = function(args){fakeDb.update(this, args)})
const fakeDb = {
findAll: async (args) => {
if (args.where) {
const keys = Object.keys(args.where);
return data.filter(el => {
return keys.filter(key => el[key] === args.where[key]).length;
});
}
return data;
},
create: async (item) => {
item.id = data[data.length - 1].id + 1;
data.push(item);
return item;
},
update: (obj, args) => {
const keys = Object.keys(args);
for (let i=0; i< data.length; i++){
if (data[i].id === obj.id) {
keys.forEach(key => data[i][key] = args[key]);
break;
}
}
},
};
sinon.stub(db.elements, 'create').callsFake(fakeDb.create);
sinon.stub(db.elements, 'findAll').callsFake(fakeDb.findAll);
const newElement = new NewElement({ formId });
const created = await newElement.create(next);
expect...
Глядя на это, я чувствую, что пишу много кода для fakeDb
и фактически не тестирую create
. Моим первоначальным ощущением было возвращение постоянного значения, например:
const fakeDb = {
create: Promise.resolve({ id: 1, forms_id: formId, previous_element_id: 0, next_element_id: 2 }),
};
Однако тогда я действительно чувствовал, что тест бесполезен? Функция все равно сможет пройти независимо от того, что я делал внутри. При тестировании принято создавать набор данных, которым вы можете манипулировать, даже если вы тогда создаете кучу методов для эмуляции БД? из этого теста и создайте какую-нибудь вспомогательную функцию, чтобы я не переписывал ее в каждом тесте. Я также не хочу слишком усложнять все это.