2015-10-29 12 views
5

Ich habe einen Ember-Service, der in erster Linie das Abrufen von Daten für ein bestimmtes Modell und die Nachkommen des Modells betrifft. Der Grund, warum ich dies in einem Dienst verwende, liegt darin, dass die Route für diesen bestimmten Typ einen Slug verwendet, der nicht der Primärschlüssel ist und daher store.query anstelle von store.find tun muss. Wenn wir dieses Modell holen, habe ich eine Logik, die den Glut-Speicher abspäht, um zu sehen, ob wir ihn von dort laden können, bevor wir zur API-Abfrage gehen. Auch dieser Anbieter beobachtet die Änderung des Slugs und aktualisiert das darauf basierende aktuelle Modell.Unit Testing Ember Services, die Daten abrufen

Das Problem, das ich habe, ist, dass dies scheint sehr wenig Dokumentation zu haben, wenn es darum geht, eine Sache wie diese zu testen. In der Tat sehe ich keinen Abschnitt zum Testen von Dienstleistungen irgendwo in den Anleitungen hier http://guides.emberjs.com/v2.1.0/

Dies ist ein Ausschnitt des Dienstes in Frage.

Ich möchte hier ein paar Szenarien mit der Store-Interaktion behaupten können. Der Lieferant ist bereits festgelegt, der Kreditor wurde vom Peek-Filter geladen und der Kreditor von der Abfrage geladen.

+0

Ich versuche auch so etwas zu tun und finde keine Dokumentation zu diesem Thema. Ich habe angefangen, einige Projekte zu betrachten, die Glut verwenden, und ich hoffe, dass ich bald einige Beispiele finde. [Hier ist was ich bisher habe] (http://pastebin.com/8sMFNdQN) wenn es überhaupt hilft. – cojomojo

+1

@cojomojo Wie würde das 'MockStore' Modul aussehen, das du auskommentiert hast? – BillPull

+0

siehe meine Antwort für ein Beispiel – cojomojo

Antwort

6

Ich denke, ich habe endlich zu einem vernünftigen Abschluss gekommen. Lassen Sie mich mit Ihnen teilen, was meiner Meinung nach der beste Weg ist, sich an Unit Testing Services zu wenden, die sich auf den Laden verlassen.

Die Antwort liegt wirklich in der Annahme, die wir beim Schreiben unit tests machen müssen. Das heißt, alles außerhalb unserer logischen Einheit sollte als ordnungsgemäß funktionieren und unsere Einheiten sollten vollständig unabhängig sein.

Daher ist es am besten mit einem Dienst, der sich auf den Laden verlässt, einen Stub oder Mock (siehe this question, um den Unterschied zwischen einem Schein und einem Stub zu verstehen) für den Laden. Ein Stummel für den Laden selbst ist ziemlich einfach. So etwas wie dies tun:

store: { 
    find: function() { 
     var mockedModel = Ember.Object.create({/*empty*/}); 
     return mockedModel; 
    }, 
    query: ... 
} 

Wenn Sie lieber ein Modell verwenden, anstatt Sie so etwas wie das folgende tun könnte (ich machte dieses sehr schnell, so dass es nicht vollständig funktionieren könnte, aber seine genug, um die Idee zu vermitteln):

import Ember from 'ember'; 

class MockStore { 
    constructor() { 
     this.models = Ember.A([]); 
    } 

    createRecord(modelName, record) { 
     // add a save method to the record 
     record.save =() => { 
      return new Ember.RSVP.Promise((resolve) => { 
       resolve(true); 
      }); 
     }; 

     if (!this.models[modelName]) { 
      this.models[modelName] = Ember.A([]); 
     } 

     this.models[modelName].pushObject(record); 

     return record; 
    } 

    query(modelName, query) { 
     let self = this; 

     return new Ember.RSVP.Promise((resolve) => { 
      let model = self.models[modelName]; 
      // find the models that match the query 
      let results = model.filter((item) => { 
       let result = true; 

       for (let prop in query) { 
        if (query.hasOwnProperty(prop)) { 
         if (!item[prop]) { 
          result = false; 
         } 
         else if (query[prop] !== item[prop]) { 
          result = false; 
         } 
        } 
       } 

       return result; 
      }); 

      resolve(results); 
     }); 
    } 
} 

export default MockStore; 

Weiter alles, was Sie tun müssen, ist die Speichereigenschaft (oder was auch immer Sie nennt es) auf Ihrem Service zu einer neuen Mock Speicherinstanz zu setzen, wenn Sie einen Test durchführen. Ich tat dies, wie so:

import Ember from 'ember'; 
import { moduleFor, test } from 'ember-qunit'; 
import MockStore from '../../helpers/mock-store'; 

let session; 
let store; 

const username = ''; 
const password = ''; 

moduleFor('service:authentication', 'Unit | Service | authentication', { 
    beforeEach() { 
     session = Ember.Object.create({}); 
     store = new MockStore(); 
    } 
}); 

test('it should authenticate the user', function (assert) { 
    // this sets the store property of the service to the mock store 
    let authService = this.subject({session: session, store: store}); 

    authService.authenticate(username, password).then(() => { 
     assert.ok(session.get('username')); 
    }); 
}); 

Die Dokumentation, diese Situationen zu testen definitiv schlecht ist, so vielleicht gibt es eine bessere Methode, aber das ist, was ich mit jetzt rollen.Auch, wenn Sie das Discourse Projekt, das ember verwendet, auschecken, folgen sie einem ähnlichen Muster zu dem, was ich hier beschrieben habe, aber in einer etwas fortgeschritteneren Art und Weise.

+0

Ich bin sicher, dass ein PR mit Dokumentation für etwas in dieser Richtung akzeptiert würde. – knownasilya

+0

@knownasilya, daran arbeite ich gerade! – cojomojo

1

Ich bin nicht sicher, das ist die Antwort, die Sie wollen, aber ich werde es trotzdem versuchen. Ein Ember-Dienst ist nicht viel mehr als ein Ember-Objekt und wenn Sie diesen Dienst "Unit-Testing" durchführen, sollte er isoliert von seinen Abhängigkeiten sein (sonst wäre es kein unit test).

Von meinem Verständnis (und das könnte falsch sein). Wenn Sie diesen Dienst testen möchten, müssen Sie den Speicher durch eine Scheinimplementierung ersetzen.

//tests/unit/services/my-service.js 
test('some scenario', function(assert) { 
    let service = this.subject({ 
    store: Ember.Object.create({ 
     peekAll(modelName){ 
      //Return array for this scenario 
     }, 
     query(model, params){ 
      //Return array for this scenario 
     } 
    }); 
    }); 
    assert.ok(service); 
}); 

Ich denke auch, das ist der Grund, warum es wenig Dokumentation Testdienste gibt. Eine Ressource, die ich über Dienste empfehle ist dieses Gespräch from the Chicago Ember Meetup

+0

Gibt es eine Möglichkeit, dies in einer Setup-Methode oder etwas zu tun? – BillPull

+0

Ich würde Sie auf die Antwort verweisen, die @comojo links unten gelassen hat. Er macht das Geschäft zu einer externen Datei und importiert sie in den Test (und instanziiert den Laden in der beforeEach) –