2017-05-08 3 views
1

Ich arbeite an einem größeren Projekt auf Angular 4. Wir erhalten JSON-Daten vom Server und zeigen diese Daten dann in einer speziellen Tabellenkomponente auf dem Client an.Konfiguration vor Jasmine Test laden

Die Spezialität der Tabelle ist, dass Sie clientseitig definieren können, welche Spalten angezeigt werden. Um herauszufinden, welche Spalten es gibt, erhalten wir eine Konfigurations-JSON-Datei vom Server. Und weil wir dieses Ding nur einmal brauchen und bevor das Modul geladen wird, habe ich den Lademechanismus in einen Schutz gestellt. Bis jetzt funktioniert das gut.

Ich habe 2 Anfragen:

  • Spalte Erklärung in der Wache
  • Daten vom Server holen und die Tabelle füllen Holen. Das ist in der Komponente gemacht

Jetzt muss ich das auch testen. Und da fängt mein Ärger an. Ich kann die JSON-Anfrage der Spalte nicht ausführen, bevor Jasmine die Komponententests ausführt.

fdescribe('Component: MyComponent',() => { 
    let fixture: ComponentFixture<MyComponent>; 
    let component: MyComponent; 

    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ 
     MyComponent 
     ], 
     providers: [ 
     FieldConfigurationService 
     ], 
     schemas: [NO_ERRORS_SCHEMA], 
     imports: [ 
     TranslateModule.forRoot({ 
      provide: TranslateLoader, 
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'resources/i18n', '.json'), 
      deps: [Http] 
     }) 
     ] 
    }).overrideComponent(MyComponent, { 
     set: { 
     providers: [] 
     } 
    }).compileComponents() 
     .then(() => { 
     fixture = TestBed.createComponent(MyComponent); 
     component = fixture.componentInstance; 
     }); 
    })); 

    it('should create an instance',() => { 
    expect(component).toBeTruthy(); 
    }); 

    describe('when field Configuration is loaded',() => { 
    beforeEach(async(() => { 
     console.log(1); 
     component.fieldConfigurationService.loadConfiguration(true); 
     console.log(2); 
    })); 

    describe('when the component is ready for use',() => { 
     console.log(3); 
    }); 
    }); 
}); 

Die Ausgabe der console.log ist 3,1,2.

Wie müsste ich die component.fieldConfigurationService.loadConfiguration(); Befehl, so dass die Sache ausgeführt wird, bevor der Block mit console.log (3) gestartet wird.

Ich habe auch versucht, dies in den "dann" Abschnitt des Testbed einzufügen. Was immer ich bisher gemacht habe, die Ausführung des Komponententests begann immer, bevor die Daten vom Server geladen wurden, aufgrund der asynchronen Art des Datenladeprozesses.

Jede Hilfe ist sehr geschätzt.

Der FieldConfigurationService sieht wie folgt aus.

@Injectable() 
export class FieldConfigurationService { 
    public config: any = {}; 
    public loadConfiguration(isUnitTest: boolean = false): Promise<any> { 
     return new Promise((resolve, reject) => { 
      if (isUnitTest) { 
      if (!this.config) { 
       this.config = this.readJSON('base/gulpdist/field-definition.json'); 
       resolve(this.config); 
      } else { 
       resolve(null); 
      } 
      } else { 
      if (!this.config) { 
       this.getJSON().subscribe(
       data => { 
        this.config = data; 
        resolve(data); 
       }, 
       error => reject(error) 
      ); 
      } else { 
       resolve(null); 
      } 
      } 
     }); 
    } 
    } 

    private readJSON(url) { 
     let xhr = new XMLHttpRequest(); 
     let json = null; 

     xhr.open('GET', url, false); 

     xhr.onload = function (e) { 
     if (xhr.status === 200) { 
      json = JSON.parse(xhr.responseText); 
     } else { 
      console.error('readJSON', url, xhr.statusText); 
     } 
     }; 

     xhr.onerror = function (e) { 
     console.error('readJSON', url, xhr.statusText); 
     }; 

     xhr.send(null); 
     return json; 
    } 
} 

Vielen Dank Simon

Antwort

1

Erstens ist dies eine schlechte Idee

public loadConfiguration(isUnitTest: boolean = false): Promise<any> { 
    return new Promise((resolve, reject) => { 
     if (isUnitTest) { 

Unit-Tests nicht in Ihre Implementierungsdetails wie diese auslaufen sollte. Was Sie sollten tun ist nur die Konfigurationsdaten zu spotten.

import { mockConfigData } from './whereever'; 

... 
const config = new FieldConfigurationService(); 
config.config = mockConfigData; 

providers: [ 
    { provide: FieldConfigurationService, useValue: config } 
] 

Sie haben also den Dienst eingerichtet, um einige falsche Daten von wo auch immer die Mock-Datei zu verwenden. Nun, was Sie tun müssen, um beheben, die resolve(null)

if (!this.config) { 
    ... 
} else { 
    resolve(null); 
} 

Was der Punkt ist null zu lösen. Der springende Punkt dieser Logik ist "Wenn es keine Konfiguration gibt, holen Sie sie, sonst zurück null?". Sollte es nicht "anders die Konfig" zurückgeben? Also reparier das. Dass sie die Config

if (!this.config) { 
    ... 
} else { 
    resolve(this.config); 
} 

Damit lösen, löst das Versprechen synchron, so müssen Sie mit dem Test nichts ändern, wenn Sie den isUnitTest Mist entfernen, die ich sehr empfehlen würden Sie tun.

+0

Hahahaha ... Danke. Ich war so auf den Komponententest konzentriert, dass ich den FieldConfigurationService vollständig ignorierte. Es funktioniert jetzt dank Ihrer Eingabe. –

Verwandte Themen