2016-05-27 8 views
1

Ok mein Setup ist wie folgt: Mit Knoten 6.2, es6-Promisify, Sinon, Sinon-as-versprochen, und babel, Unterstützung für es6 Import/Export zu transpile.sinon stub mit es6-promisified objekt

im Test Mein Code sieht in etwa wie folgt aus:

const client = restify.createJsonClient({ 
    url: 'http://www.example.com' 
}); 
export let get = promisify(client.get, {thisArg: client, multiArgs: true}); 

export default function*() { 
    yield get('/some/path'); 
} 

Und dann in meiner Testdatei so etwas wie dieses habe ich:

import * as m from mymodule; 
it('should fail', function(done) { 
    let stub = sinon.stub(m, 'get').rejects('i failed'); 
    client.get('/endpoint/that/leads/to/mymodule/call', function(err, req, res, data) { 
     stub.called.should.be.eql(true); // assertion fails!! 
     done(); 
    } 
}); 

ich auch die ursprüngliche client.get stubbing versucht haben Rufen Sie an, und das funktioniert auch nicht. Das Einzige, woran ich gearbeitet habe, ist es, mit jedem Aufruf zu promistifizieren und das ursprüngliche client.get zu stubben, was ziemlich lahm aussieht. Z.B .:

export const client = restify.createJsonClient({ 
    url: 'http://www.example.com' 
}); 
function get() { 
    return promisify(client.get, {thisArg: client, multiArgs: true}); 
} 

export default function*() { 
    yield get('/some/path'); 
} 

Und Testcode dies zu tun:

import {module_client} from mymodule; 
it('should fail', function(done) { 
    let stub = sinon.stub(module_client, 'get').yields('i failed'); 
    client.get('/endpoint/that/leads/to/mymodule/call', function(err, req, res, data) { 
     stub.called.should.be.eql(true); // assertion succeeds 
     done(); 
    } 
}); 

Und so ist die Frage, ob es nicht ganz klar ist, ist, warum hat mein Original-Code nicht? Und gibt es eine Möglichkeit, den Stub zu arbeiten, ohne jedes Mal das Original zu verwerfen (z. B. wie funktionieren andere Leute so)?

EDIT:

Aktueller Code sieht wie folgt aus:

const client = restify.createJsonClient({ 
    url: 'http://www.example.com' 
}); 

export let get = promisify(client.get, {thisArg: client, multiArgs: true}); 

export default function*() { 
    try { 
     console.log(exports.get); // <= a large sinon stub object, I'll post that below 
     yield exports.get(); // <= throws here, "exports.get is not a function" 
    } 
    catch(ex) { 
     log.error('got an error', ex); 
     throw ex; 
    } 
} 

Die console.log druckt die folgenden:

{ [Function: proxy] 
    isSinonProxy: true, 
    reset: [Function], 
    invoke: [Function: invoke], 
    named: [Function: named], 
    getCall: [Function: getCall], 
    getCalls: [Function], 
    calledBefore: [Function: calledBefore], 
    calledAfter: [Function: calledAfter], 
    withArgs: [Function], 
    matches: [Function], 
    printf: [Function], 
    calledOn: [Function], 
    alwaysCalledOn: [Function], 
    calledWith: [Function], 
    calledWithMatch: [Function], 
    alwaysCalledWith: [Function], 
    .... 

EDIT2:

Und FWIW, die babel erzeugt Code produziert dies:

let get = exports.get = (0, _es6Promisify2.default)(client.get, { thisArg: client, multiArgs: true }); 

EDIT3:

Ok Super seltsam. Ich änderte meine Quelle dieses stattdessen zu tun:

const client = restify.createJsonClient({ 
    url: 'http://www.example.com' 
}); 

export let get = promisify(client.get, {thisArg: client, multiArgs: true}); 

export default function*() { 
    try { 
     let thePromise = exports.get(); // e.g. call exports.get on separate line from the yield 
     yield thePromise; // and the throw now says 'undefined is not a function'. I should note that in both cases, the stack trace shows the error on node_modules/co/index.js at line 65. 
    } 
    catch(ex) { 
     log.error('got an error', ex); 
     throw ex; 
    } 
} 
+0

'get()' wird nicht exportiert, daher ist 'module_client.get()' in Ihrem Testcode nicht definiert. Aber selbst wenn es exportiert wird, gibt es immer noch Probleme, die von ES6 verursacht werden (zumindest denke ich). Ich werde sehen, ob ich als Antwort schreiben kann. – robertklep

+0

Wenn du meinst, 'Get' wird im zweiten Beispiel nicht exportiert, hast du recht, ich habe da einen Fehler. Was ich meinte war, dass der ursprüngliche restify.client als module_client exportiert wird. Und ich stoße das an. Was funktioniert. – Kevin

+0

Oh sorry, natürlich ist es! Meine Antwort sollte immer noch auf den ersten Fall angewendet werden, der zweite Fall wird umgangen, indem zur Laufzeit statt zur Zeit des Imports eine Promistifizierung erfolgt. – robertklep

Antwort

2

Das Problem letztlich zu tun hat, mit wie ES6 Import/Export erfolgt, und zwar, wie sie Ihren Code besser aussehen aber verhindern leicht Spionage/Anstoßen.

dieses Beispiel Modul Nehmen:

import * as sinon from 'sinon'; 
import * as should from 'should'; 
import setup, * as myModule from './my-module'; 

it('should call get()',() => { 
    let stub = sinon.stub(myModule, 'get'); 
    setup(); 
    stub.called.should.eql(true); 
}); 

Sie werden sehen, dass die ursprüngliche get() aufgerufen wird, und nicht der Stub:

// my-module.js 
function someFunction() { 
    console.log('original'); 
}; 

export let get = someFunction; 

export default function() { 
    get(); 
}; 

Ein Testfall für diesen Code wie folgt aussehen könnte. Dies liegt daran, dass get im Modul eine lokale (zum Modul) Referenz ist. Sinon stubbing ein weiterer Verweis auf die gleiche Funktion, in dem exportierten Objekt.

Um diese Arbeit zu machen, anstatt eine lokale Referenz im Modul verwenden, müssen Sie die eine in dem exportierten Objekt verwenden:

export default function() { 
    exports.get(); 
}; 

Welche leider für hässlichen Code machen.

+0

Also habe ich getan wie du gesagt hast, was Sinn macht. Aber ich bekomme einen weiteren Fehler. In dem zu testenden Code gibt es einen Ausdruck, wo ich exports.get anrufe und sage "exports.get ist keine Funktion". Wenn ich console.log auf exports.get kurz vor dem Aufruf zeige, zeigt es, dass es ein Objekt ist - das Sinon-Stub-Objekt. Ich kann es in meine Frage einfügen, aber das Objekt ist ziemlich groß. – Kevin

+0

Ich habe meine Antwort so bearbeitet, dass der Code Ihr erstes Beispiel ein wenig mehr nachahmt. – robertklep

+0

OK, also ist das exports.get das richtige Objekt, es ist das sinon-Stub-Proxy-Objekt. So ist meine Verwirrung, warum es jetzt abstürzt, exports.get zu sagen, ist keine Funktion. Ich meine, es ist keine Funktion, es ist ein Proxy. Aber es ist nicht anders als das, was Sinon woanders in meinem Code macht. Damit...? – Kevin