mercredi 14 septembre 2016

Angular 2 TestBed, Mocking Methods without Dependency Injection

Using TestBed, we are able to create mock classes for classes that are available with dependency injection. For example, MyButtonClass has access to ElementRef and MyService since they are implemented with dependency injection, and so we can override them. The problem I have is that, to write a Jasmine test, I have to create mock classes to override methods of classes that are not accessed with dependency injection.

In this case, ScriptLoader.load will load ThirdPartyCheckout in the global space. This means, it might not be available when Jasmine reads what is inside the subscribe operator. For this reason, I would like to mock the former first and then the latter after. Or maybe there is a different way to get around this.

It would be great if someone can suggest a way to create mock classes to override the ScriptLoader.load method and ThirdPartyCheckout.configure method.

The directive to be tested:

@Directive({
    selector: '[myButton]'
})
export class MyButtonClass implements AfterViewInit {

    private myKey: string;

    constructor(private _el: ElementRef, private myService: MyService) {}

    ngAfterViewInit() {
        this.myService.getKey()
            .then((myKey: string) => {
                this.myKey = myKey;
                ScriptLoader.load('http://ift.tt/2cINUrR', this._el.nativeElement)
                    .subscribe(
                        data => {
                            this.handeler = ThirdPartyCheckout.configure(<any>{
                                key: this.myKey
                                // etc
                                // and some methods go here
                            });
                        },
                        error => {
                            console.log(error);
                        }
                    );
        });
    }
}

Here is the test code:

@Component({
    selector: 'test-cmp',
    template: ''
})
class TestComponent {}

class mockMyService {
    getKey() {
        return Promise.resolve('this is a key in real code');
    }
}

describe('myButton', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent, MyButtonClass],
            providers: [
                {provide: MyService, useClass: mockMyService}
            ]
        });
    });

    describe('ngAfterViewInit', fakeAsync(() => {
        const template = '<div><div myButton></div></div>';
        TestBed.overrideComponent(TestComponent, {set: {template: template}});
        let fixture = TestBed.createComponent(TestComponent);
        fixture.detectChanges();
        tick();
    }));
});

Aucun commentaire:

Enregistrer un commentaire