Возвращаемое значение из подписки в Angular - PullRequest
1 голос
/ 05 ноября 2019

Я пытаюсь понять подписки rxjs, Observables и т. Д., Но это мне чуждо. У меня есть сервис с методом, на который я подписываюсь. Метод выглядит следующим образом:

create(product: any): Observable<any> {
    return this.http.post<any>(`${environment.apiUrl}/products`, product).pipe(
        map((response: any) => {
            this.toastr.success(response.message);
            return response.model;
        }),
    );
}

Затем в моем компоненте есть метод сохранения, и для тестов я хочу получить возвращенную модель. Итак, я сделал это:

onSubmit(): Observable<any> {
    this.submitted = true;

    if (this.saveForm.invalid) return;

    let valid = true;
    let categoryId = this.fields[0].categoryId;
    let product = {
        categoryId: categoryId,
    };

    this.fields.forEach(field => {
        let value = this.f[field.name].value;
        if (valid) {
            valid = value !== undefined;
        }
        product[field.name] = value;
    });

    product['state'] = valid ? 'verified' : 'raw';

    var response = new Subject<any>();
    this.productService.create(product).subscribe(data => {
        response.next(data);
    });
    return response.asObservable();
}

В моем тесте я написал это:

it('should save a product and remove from range', () => {
    let component = spectator.component;

    component.onSubmit().subscribe(product => {
        expect(product.gtin).toBe(0);
        expect(product.state).toBe('verified');
        console.log(product);
    });

    expect(component.range.length).toBe(1);
    expect(component.saveForm.controls['gtin'].value).toBe(1);
});

Я предполагаю, что сделал это неправильно. Тест проходит, но я думаю, что это потому, что подписка никогда не достигается. Может кто-нибудь сказать мне, что мне нужно сделать?

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Вместо

var response = new Subject<any>();
    this.productService.create(product).subscribe(data => {
        response.next(data);
    });
    return response.asObservable();

Просто сделайте

return this.productService.create(product);
0 голосов
/ 05 ноября 2019

Ваше предположение верно, тело подписки никогда не вызывается в вашем тесте ... поскольку наблюдаемое не даст результата.

Вам нужно изменить тест следующим образом:

let httpTestingController: HttpTestingController;

beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule, // <== very important to mock the request
      ],
    });

    (...)

    httpTestingController = TestBed.get(HttpTestingController);
  });

it('should save a product and remove from range', async done => {
    let component = spectator.component;

    component.onSubmit().subscribe(product => {
        expect(product.gtin).toBe(0);
        expect(product.state).toBe('verified');
        console.log(product);
        done();
    });

    expect(component.range.length).toBe(1);
    expect(component.saveForm.controls['gtin'].value).toBe(1);

    //This part simulates the backend responding your .onSubmit() call: 
    const testProductData = {your_atributes} // <== this should be what you expect to receive from the backend;
    const mockRequest = httpTestingController.expectOne(`${environment.apiUrl}/products`);
    mockRequest.flush(testProductData); // <== this call will make your observable respond.
});

Этот done обратный вызов в тесте - это то, что заставит ваш тест работать для требований асинхронных тестов, подобных вашим. Тест не пройден, если тело подписки не вызывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...