3

TestBedを使用すると、依存性注入で利用可能なクラスのモック クラスを作成できます。たとえば、これらは依存性注入で実装されているため、andMyButtonClassにアクセスできるため、それらをオーバーライドできます。私が抱えている問題は、Jasmine テストを作成するには、依存性注入でアクセスされないクラスのメソッドをオーバーライドするモック クラスを作成する必要があることです。ElementRefMyService

この場合、グローバル空間ScriptLoader.loadにロードされます。ThirdPartyCheckoutこれは、Jasmine が subscribe オペレーターの内容を読み取るときに利用できない可能性があることを意味します。このため、前者を最初にモックし、次に後者をモックしたいと思います。または、これを回避する別の方法があるかもしれません。

ScriptLoader.loadメソッドとメソッドをオーバーライドするモック クラスを作成する方法を誰かが提案できれば、それは素晴らしいことThirdPartyCheckout.configureです。

テストするディレクティブ:

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

テストコードは次のとおりです。

@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();
    }));
});
4

1 に答える 1

4

関数は第一級市民であるため、新しい関数をそれに割り当てることができます

let originalFn;

beforeEach(() => {
  originalFn = ScriptLoader.load;
});

afterEach(() => {
  ScriptLoader.load = originalFn;
});

it('...', fakeAsync(() => {
  ScriptLoader.load = (url, el: Element): Observable<string> => {
    return Observable.of('HelloSquirrel');
  };
  ...
}));

これ以外に、DI の使用を検討することもできます。DI を使用する主な理由の 1 つは、テスト容易性を高めることです。ScriptLoaderメソッドを非静的メソッドにするだけで、サードパーティのライブラリの場合は、抽象化サービスレイヤーとして作成するだけです。

于 2016-09-14T13:05:07.740 に答える