I'm trying to test a component that on her ngOnInit subscribe to observable in a service, and change the behavior of the component according to the value got from the observable. I reduced my problem to these pieaces of code.
the component:
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'app-root',
template: `
<div>
<h3>currentValue is {{currentValue}}</h3>
<div>
<button (click)="changeTo(true)">true</button>
<button (click)="changeTo(false)">false</button>
</div>
</div>
`,
styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
public currentValue: boolean;
constructor(
private appService: AppService
) { }
ngOnInit() {
this.appService.getObs().subscribe(newValue => this.currentValue = newValue);
}
changeTo(value: boolean) {
this.appService.setObs(value);
}
}
the service:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppService {
private obs = new BehaviorSubject<boolean>(false);
getObs(): Observable<boolean> {
return this.obs.asObservable();
}
setObs(value: boolean): void {
this.obs.next(value);
}
}
the test:
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { of } from 'rxjs';
describe('AppComponent', () => {
let mockAppService = jasmine.createSpyObj(['setObs', 'getObs']);
let app: AppComponent
let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
{ provide: AppService, useValue: mockAppService }
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
mockAppService.getObs.and.returnValue(of(false));
app = fixture.debugElement.componentInstance;
fixture.detectChanges();
});
it('should create the app', () => {
expect(app).toBeTruthy(); // pass
});
it('should set currentValue to false', () => {
expect(app.currentValue).toBe(false); // pass
});
it('should change currentValue to true', () =>
mockAppService.// some how to do next(true)
fixture.detectChanges();
expect(app.currentValue).toBe(true); //
});
});
I expect to have an easy way to control the values that the mockObservable returned. I want to change the value between tests and test each of the options.
I saw the option of jasmine-marbles but it looks to complicated for such an issue. Does any one know an easy way to do that?
EDIT: I want to have the ability to call next() on the observale, without calling setObs (lets say it's private, actually in my app I don't have setObs function, the call for next() is in more complex function)