Проверить наблюдаемое значение из BehaviorSubject в подписке - PullRequest
0 голосов
/ 19 июня 2020

У меня есть простая служба, которая запрашивает Интернет, а затем на основе возврата генерирует событие через BehaviorSubject

export class ProducerService {
    static readonly baseUrl = `${environment.apiUri}/producers`
    private readonly admin = new BehaviorSubject<boolean>(false)
    readonly admin$ = this.admin.asObservable()

    constructor(private readonly http: HttpClient) {
    }

    queryAdmin(): void {
        this.http.get<boolean>(`${ProducerService.baseUrl}/admin`)
            .subscribe(x => this.admin.next(x))
    }
}

Теперь я пытаюсь написать тест, который проверяет если true, то переменная admin$ получает значение true. Я пробовал это вот так:

it('should emit true when an admin', async(() => {
    service.admin$.subscribe(x => expect(x).toBeTrue())

    service.queryAdmin()
    const req = httpMock.expectOne({url: `${ProducerService.baseUrl}/admin`, method: 'GET'})
    req.flush(true)
}))

Это не удается, хотя говорит: «Ожидаемое ложное значение истинно». Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 19 июня 2020

BehaviorSubject является «горячим», поэтому он готов к go, когда вы подписываетесь на него, и он имеет начальное значение false, затем вы утверждаете false дляBeTrue.

Попробуйте отфильтровать ложные значения с использованием оператора фильтра Rx js.

import { filter } from 'rxjs/operators';
....
it('should emit true when an admin', async((done) => {
    service.admin$.pipe(
      filter(admin => !!admin), // the value of admin has to be true for it to go into the subscribe block
    ).subscribe(x => { 
      expect(x).toBeTrue(); 
      done(); // add the done function as an argument and call it to ensure
    });       // test execution made it into this subscribe and thus the assertion was made
              // Calling done, tells Jasmine we are done with our test.

    service.queryAdmin()
    const req = httpMock.expectOne({url: `${ProducerService.baseUrl}/admin`, method: 'GET'})
    req.flush(true)
}))
0 голосов
/ 20 июня 2020

Здесь пришлось сделать несколько вещей. Не удалось использовать asyn c или ему не понравился метод done. Пришлось выполнить фильтр, подобный предложенному @ AliF50, и мне пришлось передать значение 1 вместо истины. Итак, я получил это для теста:

it('should emit true when an admin', (done) => {
    service.admin$
        .pipe(filter(x => x))
        .subscribe(x => {
            expect(x).toBeTrue()
            done()
        })

    service.queryAdmin()
    const req = httpMock.expectOne({url: `${ProducerService.baseUrl}/admin`, method: 'GET'})
    req.flush(1)
})

Это также означало, что мне пришлось изменить свой метод queryAdmin, чтобы я сделал !! следующим образом:

queryAdmin(): void {
    // This is being done for the producer.service.spec.ts file because it
    // won't decode a 'true' value automatically, so I have to pass in a 1
    // as the body (i.e. a true value) and then this !!x converts that to true.
    // noinspection PointlessBooleanExpressionJS
    this.http.get<boolean>(`${ProducerService.baseUrl}/admin`).subscribe(x => this.admin.next(!!x))
}
...