Angular 2 TestBed, Mocking Methods without Dependency Injection
<p>Using <a href="https://angular.io/docs/ts/latest/api/core/testing/index/TestBed-class.html" rel="nofollow">TestBed</a>, we are able to create mock classes for classes that are available with dependency injection. For example, <code>MyButtonClass</code> has access to <code>ElementRef</code> and <code>MyService</code> 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.</p>

<p>In this case, <code>ScriptLoader.load</code> will load <code>ThirdPartyCheckout</code> 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.</p>

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

<p>The directive to be tested:</p>

<pre><code>@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) =&gt; {
                this.myKey = myKey;
                ScriptLoader.load('https://thirdpartyurl.js', this._el.nativeElement)
                    .subscribe(
                        data =&gt; {
                            this.handeler = ThirdPartyCheckout.configure(&lt;any&gt;{
                                key: this.myKey
                                // etc
                                // and some methods go here
                            });
                        },
                        error =&gt; {
                            console.log(error);
                        }
                    );
        });
    }
}
</code></pre>

<p>Here is the test code:</p>

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

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

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

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