I would inject a fake service using the DI system, which would mean writing the tests something like this:
describe('your component', () => {
let fixture: ComponentFixture<YourComponent>;
let fakeService;
let dragSubject = new ReplaySubject(1);
...
beforeEach(async(() => {
fakeService = {
drag: dragSubject.asObservable(),
...
};
TestBed.configureTestingModule({
declarations: [YourComponent, ...],
providers: [
{ provide: DragulaService, useValue: fakeService },
...
],
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(YourComponent);
fixture.detectChanges();
});
it('should do something when a drag event occurs', () => {
dragSubject.next({ ... });
fixture.detectChanges();
...
});
});
This allows you to trigger "drag events" whenever you like by calling .next
on the subject, which causes subscribers to the fields on the fake service to get called. You can then make assertions on the outcomes you expect from that.
Note that you do not need to call constructor
yourself; this method is invoked when the DI system instantiates your component, i.e. when TestBed.createComponent
is called.
I would recommend that you don't spy on the component methods (e.g. this.onDrag
) and just make sure that they get called, but rather test that whatever those methods should do as a result happens; this makes the tests more robust to changes in the specific implementation (I wrote a bit about this on my blog: http://blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html).
DragulaService
using the test bed and spy on its methods? – MisapprehensionTestBed.createComponent(YourComponent)
. – Misapprehensionnew YourComponent(...)
, but you should let the DI system do its job. That's how the unit will be used in practice, think about its public interface as the other components see it. As below, it sounds like you're writing (or trying to write) brittle tests that are too closely tied to current implementation. – Misapprehension