2017-12-22 10 views
0

Ich habe eine eckige Komponente, die das Autorize.nets Accept.js SDK verwendet, um eine Zahlung abzuschließen. Ich möchte das Accept.js-Skript nicht laden, es sei denn, der Benutzer befindet sich auf dem Zahlungsbildschirm. Daher füge ich das Skript der Seite über eine Methode hinzu, die ich unter der Nummer onInit in der Komponente anrufe.Angular Accept.js Unterbrechungseinheit Tests 'Reference Error: Accept ist nicht definiert'

some.component.ts

ngOnInit { 
    this.addAcceptJsScript(); 
} 

private addAcceptJsScript(): void { 
    const element = document.createElement('script'); 
    element.src = environment.acceptJsUrl; 
    element.type = 'text/javascript'; 
    document.getElementsByTagName('head')[0].appendChild(element); 
} 

some.service.ts

declare var Accept: any; 

@Injectable() 
export class SomeService { 
    private sendPaymentToAuthNet(paymentPayload): void { 
    Accept.dispatchData(paymentPayload, this.handleAuthNetResponse); 
    } 
} 

Dies funktioniert für die Benutzer fein wie das Skript im DOM und verfügbar geladen wird, wenn die Komponente ruft den Dienst auf, der die Accept API

verwendet Allerdings hat mein Komponententest in dem Dienst, der die API verwendet, keinen Verweis darauf, was Accept ist, wenn es versucht, die Codezeile zu testen, wo ich Accept.dispatchData(...) die Testfehler herausrufende 'Verweisfehler: Akzeptieren ist nicht definiert ".

Ich habe verschiedene Arten der Verspottung versucht akzeptieren, aber keiner von ihnen machen es für den Test verfügbar. Wie gehe ich vor, um meinen Schein Accept in den Dienst zu injizieren, so dass es deklariert wird, wenn der Code versucht, es zu verwenden?

Antwort

0

Probleme mit Tests weisen normalerweise auf Fehler im Anwendungsdesign hin.

document sollte vorzugsweise ein Provider sein, weil es angeblich verspottet wird, um das Hinzufügen von Skriptelementen zu echtem DOM zu vermeiden. Es gibt DOCUMENT Provider bereits, dass in die Komponente anstelle von document global injiziert werden kann. Und in Prüfstand spottet:

{ 
    provide: DOCUMENT, 
    useValue: jasmine.createSpyObj('document', ['createElement', 'getElementsByTagName']) 
} 

Wo createElement und getElementsByTagName Jasmin Spione so konfiguriert werden, sollten angemessene Mock-Objekte zurück.

Accept sollte aus Testzweckgründen ebenfalls ein Provider sein. Der Wert kann window['Accept'] wie in this answer gezeigt zugewiesen werden und im Testbett verspottet werden.

0

Ich musste nur den Pfad für die Accept.js CDN Objekt

files: [ 
    { pattern: './src/test.ts', watched: false }, 
    { pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: true }, 
    { pattern: 'https://jstest.authorize.net/v1/Accept.js', nonull: true } 
] 
+0

Ich würde in der karma.config in meinen Dateien enthalten erwarten, dass Sie Unit-Tests und nicht die Integration ausführen. Das Testen gegen reale Dinge ist in Komponententests schlecht, weil dies die Isolation unterbricht. – estus

+0

Ich teste nicht dagegen, ich brauche es nur definiert. – efarley

+0

Der Punkt hier ist, dass echte Accept.dispatchData (und noch wichtiger, document.createElement) nicht einmal eine Chance haben, im Komponententest aufgrund möglicher Nebenwirkungen aufgerufen werden. Damit soll DI helfen. Die Alternative besteht darin, ein Fenster zu definieren.Akzeptieren in beforeEach, das für Angular weniger idiomatisch ist. – estus

Verwandte Themen