2016-05-27 7 views
1

ОК, моя настройка выглядит следующим образом: Использование узла 6.2, es6-promisify, sinon, sinon-as-обещано и babel для передачи поддержки импорта/экспорта es6.sinon stub с es6-promisified object

Мой код тестируемой выглядит примерно так:

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'); 
} 

, а затем в моем тестовом файле у меня есть что-то вроде этого:

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

Я также попытался гася оригинальный client.get вызова, и это тоже не работает. Единственное, что я получил на работу, - это обещание «на лету» с каждым вызовом, и наложение первоначального client.get, который кажется довольно хромым. Например .:

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'); 
} 

И тестовый код делает это:

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

И поэтому вопрос, если это не совсем очевидно, это почему мой исходный код не работает? И есть ли способ сделать работу с заглушкой без предварительного изложения первоначального обновления каждый раз (например, как другие люди получают такую ​​работу)?

EDIT:

Текущий код выглядит следующим образом:

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; 
    } 
} 

The console.log гравюр следующее:

{ [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:

И FWIW, Вавилонская сгенерированных код производит это:

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

EDIT3:

Ok супер странно. Я изменил мой источник, чтобы сделать это вместо того, чтобы:

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()' не экспортируется, поэтому 'module_client.get()' не определен в вашем тестовом коде. Но даже если он был экспортирован, все еще есть проблемы, вызванные ES6 (по крайней мере, я думаю). Я посмотрю, смогу ли я писать, это ответ. – robertklep

+0

, если вы имеете в виду «get», не экспортируется во втором примере, вы правы, у меня есть ошибка. я имел в виду, что исходный файл restify.client экспортируется как module_client. И я обманываю это. Что работает. – Kevin

+0

О, извините, конечно! Мой ответ все равно должен применяться к первому случаю, второй случай работает вокруг него, пообещав во время выполнения, а не во время импорта. – robertklep

ответ

2

Проблема в конечном счете, к тому, как ES6 импорт/экспорт работать, и, в частности, как они делают ваш код выглядеть лучше но предотвратить легкий шпионаж/заглушек.

Возьмите этот пример модуля:

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

export let get = someFunction; 

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

Тестовый пример для этого кода может выглядеть следующим образом:

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); 
}); 

Вы увидите, что первоначальный get() вызывается, а не заглушки. Это связано с тем, что в модуле get является локальной (для модуля) ссылкой. Sinon stubbing другой ссылка на ту же функцию, в экспортированном объекте.

Чтобы сделать эту работу, вместо того, чтобы использовать локальную ссылку в модуле, вы должны использовать один в экспортируемом объекте:

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

Который, увы, делает для уродливого кода.

+0

Так я и сделал, как вы сказали, что имеет смысл. Но я получаю еще одну ошибку. В тестируемом коде он бросает туда, где я вызываю export.get, говоря: «export.get не является функцией». Если я делаю console.log на export.get непосредственно перед вызовом, он показывает, что это объект - объект-заглушка sinon. Я могу вставить его в свой вопрос, но объект довольно большой. – Kevin

+0

Я отредактировал свой ответ, чтобы код имитировал ваш первый пример немного больше. – robertklep

+0

ОК, так что export.get - это правильный объект, это прокси-сервер sinon. Поэтому моя путаница - это то, почему она теперь терпит крах, говоря, что export.get не является функцией. Я имею в виду, что это не функция, это прокси. Но это не отличается от того, что синус делает в другом месте моего кода. Так...? – Kevin

Смежные вопросы