Как проверить оператор forkJoin() с жасминовыми шариками
Я создал сервис, который отправляет данные на сервер, данные были заполнены пользователем в пользовательском интерфейсе. Пользователь также может загрузить любой файл, чтобы отправить его на сервер. Я пытаюсь проверить эту функциональность с жасминовыми шариками.
Вот мой сервисный код:
export class FormSubmitService {
constructor(private http: HttpClient) {}
public submit(data, attachments) {
const observables = [
...attachments.map((file) => this.uploadAttachment(file)),
];
return forkJoin(...observables)
.pipe(
defaultIfEmpty([]),
map((tokens) => {
return tokens.map((tokenObj) => tokenObj.attachment_token);
}),
switchMap((tokens: string[]) => {
const formData = {
data,
attachments: tokens,
};
return this.submitForm(formData);
}),
);
}
private uploadAttachment(attachment: File) {
const attachmentData: FormData = new FormData();
attachmentData.append('attachment', attachment, attachment.name);
return this.http.post(
'/some/form/endpoint/attachments',
attachmentData,
);
}
private submitForm(userData: UserData) {
return this.http.post(
`/some/form/endpoint/form`,
userData,
);
}
}
Если пользователь добавляет одно или несколько вложений, то перед тем, как отправлять пользовательские данные на сервер, мне нужно загрузить каждое приложение на сервер, чтобы получить маркер каждого вложения, который позже я сохраню в массиве. Я делаю это с forkJoin()
, ожидая загрузки всех вложений и затем используя switchMap
для отправки пользовательских данных.
Вот два моих тестовых примера (один работает, другой не работает):
describe('SubmitFormData', () => {
let service: FormSubmitService;
let http: jasmine.SpyObj<HttpClient>;
beforeEach(() => {
http = jasmine.createSpyObj('HttpClient', ['post']);
service = new FormSubmitService(http);
});
describe('#submit', () => {
const file = new File([''], 'filename', { type: 'image/png' });
const attachments = [file];
const data = {
name: 'name',
description: 'description',
};
// NOT WORKING!
it('submit with attachment', () => {
const expected = cold('-a--b-', { a: ['token'], b: { id: 'id_123' } }); // FAIL!
// const expected = cold('----'); // SUCCESS!
http.post.and.returnValues(
cold('-a-', { a: [{ attachment_token: 'token' }] }),
cold('-a-', { a: { id: 'id_123' } }),
);
const output = service.submit(data, attachments);
expect(output).toBeObservable(expected);
expect(http.post).toHaveBeenCalled();
});
// WORKING!
it('submit without attachment', () => {
const response = {
id: 'id_123',
};
const expected = cold('-a-', { a: response });
http.post.and.returnValues(
cold('-a-', { a: { id: 'id_123' } }),
);
const output = service.submit(data, []);
expect(output).toBeObservable(expected);
expect(http.post).toHaveBeenCalled();
});
});
});
Проверка, где данные формы без вложений, успешна, но проверка, где данные формы с вложением завершается неудачей.
Сообщение об ошибке от сбоя:
✖ отправить с вложением HeadlessChrome 71.0.3578 (Mac OS X 10.14.2) Ошибка: ожидается, что $.length = 0 равно 2. Ожидается, что $[0] = не определено равным объекту ({ frame: 10, уведомление: уведомление ({вид): 'N', значение: [ 'token' ], ошибка: не определено, hasValue: true }) }). Ожидаемый $[1] = неопределенный для равного объекта ({ frame: 40, message: Notification({ kind: 'N', value: Object({ id: 'id_123' }), ошибка: undefined, hasValue: true }) }).
Похоже на output
не испускает наблюдаемое в неудачном тесте и является undefined
Но вопрос - почему? Потому что в другом тесте он испускает его, когда не отправляет вложение и не использует forkJoin()
,
У кого-нибудь есть идея, почему это может быть так? Спасибо!
1 ответ
Исправлена эта проблема, проблема была с первой наблюдаемой, которая была возвращена из http.post
вызов - cold('-a-', { a: [{ attachment_token: 'token' }] }),
, Он не испускал новых наблюдаемых, и в этот момент все испытания прекратились. Изменил это на of({ attachment_token: 'token' }),
и тест пройден успешно
Вот код:
it('submit with attachment', () => {
const response = {
id: 'id_123',
};
http.post.and.returnValues(
of({ attachment_token: 'token' }),
cold('-a', { a: response }),
);
const expected = cold('-a', { a: response });
const output = service.submit(data, attachments);
expect(output).toBeObservable(expected);
expect(http.post).toHaveBeenCalledTimes(2);
})