Reputation: 10345
I've got a simple service that queries the web and then based on the return, it emits an event through a 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))
}
}
Now I'm trying to write a test that verifies if true is passed in that the admin$
variable gets set to true. I tried it like this
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)
}))
That fails though saying "Expected false to be true". What am I doing wrong?
Upvotes: 0
Views: 1351
Reputation: 10345
Had to do multiple things here. Couldn't use async or it didn't like the done method. Had to do the filter like @AliF50 suggested, and I had to pass in a value of 1 instead of true. So I ended up with this for the test:
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)
})
That also meant I had to modify my queryAdmin
method so that I did the !!
like so:
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))
}
Upvotes: 0
Reputation: 18869
The BehaviorSubject is "hot" so it is ready to go when you subscribe to it and it has an initial value of false, then you're asserting false toBeTrue.
Try to filter out the false values using the filter operator of Rxjs.
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)
}))
Upvotes: 1