Node.js 我怎样才能通过摩卡咖啡的虚假承诺进行测试?

Node.js 我怎样才能通过摩卡咖啡的虚假承诺进行测试?,node.js,unit-testing,mocking,promise,mocha.js,Node.js,Unit Testing,Mocking,Promise,Mocha.js,我的node.js代码是: function getPatientNotificationNumbers(patientId) { patientId = patientId && patientId.toString(); var sql = "SELECT * FROM [notification_phone_number] "; sql += "WHERE patient_id = " + escapeSql(patientId); ret

我的node.js代码是:

function getPatientNotificationNumbers(patientId) {
    patientId = patientId && patientId.toString();

    var sql = "SELECT * FROM [notification_phone_number] ";
    sql += "WHERE patient_id = " + escapeSql(patientId);
    return sqlServer.query(sql).then(function(results) {
        var phoneNumbers = _.map(results[0], function (result) {
            var obj = {
                id: result.id,
                phoneNumber: result.phone_number,
                isPrimary: result.is_primary,
                isVerified: result.is_verified,
                patientId: result.patient_id
            }
            return obj;
        });

        return phoneNumbers;
    });
}
非常简单和直接。我想测试的是,这个函数的返回,经过正确解析,是一个匹配该格式的
电话号码数组

sqlServer
是上面的
require
'd,我在这个文件中有很多东西
require
'd。为了剔除它们,我使用了
mocky
,这似乎非常棒

到目前为止,这是我的测试:

before(function() {
    deferred = Q.defer();
    mockery.enable();
    moduleConfig.init();
    mockery.registerSubstitute('moment', moment);
    mockery.registerAllowable('../../util');

    mockStubs.sqlServer = {
        query: sinon.stub().returns(deferred.promise)
    }

    mockery.registerMock('../../db/sqlserver', mockStubs.sqlServer);

    methods = require('../../../rpc/patient/methods');
});

beforeEach(function() {
    deferred = Q.defer();
})

it('should get the patient notification numbers', function(done) {
    // sinon.spy(sqlServer, 'query').and.returnValue(deferred.promise);
    deferred.resolve('here we go');
    methods.getPatientNotificationNumbers(1).then(function(result) {
        console.log(result);
        done();
    });


});
但是,它永远不会通过我的代码中的
sqlServer.query
。因此,
结果
毫无意义。我也试过这样的方法:

function getNumbers(results) {
    var phoneNumbers = _.map(results[0], function (result) {
        var obj = {
            id: result.id,
            phoneNumber: result.phone_number,
            isPrimary: result.is_primary,
            isVerified: result.is_verified,
            patientId: result.patient_id
        }
        return obj;
    });

    return phoneNumbers;
}

module.exports = getNumbers;
response=methods.getPatientNotificationNumber(1)

但是当我
console.log(response)
时,它基本上是
{state:'pending'}
,我想这是一个未解决的承诺

所以我到处都是,我愿意使用任何使事情变得简单的库。我没有嫁给
嘲弄
西农
或其他任何人。任何建议都会有帮助


谢谢

在我看来,您的意图是测试传递
.then()
方法的函数,而不是
sqlserver
库,也不是它返回的实际承诺。我们可以假设这些已经过测试

如果是这种情况,您可以简单地计算出该函数(从SQL结果中提取电话号码的函数)并单独测试它

您的代码将变成以下内容:

var getNumbers = require('./getNumbers');
function getPatientNotificationNumbers(patientId) {
    patientId = patientId && patientId.toString();

    var sql = "SELECT * FROM [notification_phone_number] ";
    sql += "WHERE patient_id = " + escapeSql(patientId);
    return sqlServer.query(sql).then(getNumbers);
}
。。。而您的
/getNumbers.js
文件看起来像:

function getNumbers(results) {
    var phoneNumbers = _.map(results[0], function (result) {
        var obj = {
            id: result.id,
            phoneNumber: result.phone_number,
            isPrimary: result.is_primary,
            isVerified: result.is_verified,
            patientId: result.patient_id
        }
        return obj;
    });

    return phoneNumbers;
}

module.exports = getNumbers;
现在,您可以独立进行测试:

var getNumbers = require('../path/to/getNumbers');

...

it('should get the patient notification numbers', function(done) {
    var sampleResults = [ ... ]; // sample results from sqlServer
    var phoneNumbers = getNumbers(sampleResults);
    assert(...); // make what ever assertions you want
});

我会缩小一点,考虑一下测试策略。假设目标是在sql server上测试模型层(方法)。这可以在不中断sql server的情况下完成。您的测试套件层可以有一组util方法来创建、初始化和删除数据库,这些方法可以从之前、之前等调用。 这样做的好处:

  • 测试真实的产品代码路径(比存根代码路径)更好
  • 如果您怀疑底层bug会产生噪音,那么stubing会更好。sqlserver层可能是稳定的
  • 模型层似乎足够简单,不需要单独测试
  • 如果您试图在模型层中测试sqlserver故障处理,那么stubing是有意义的。然后存根层可以伪造这样的错误——在模型代码中使用错误路径
    这是基于对您的问题的有限看法。如果还有更多的话。Pl确实可以共享,我们可以从中获取。

    因此,另一种方法是结合使用and

    这意味着您不需要更改生产代码,您可以使用以下内容轻松地开始测试不满意的路径:

    it('handles Sql errors', function(done) {
      mockSql.setup.query.toRejectWith(new Error('Booom'));
      sut.getPatientNotificationNumbers(id)
        .then(function(){
          done('should not have resolved');
        })
        .catch(function(e) {
           e.should.be.an.Error;
           e.message.should.eql('Booom');
           done();
        });
    });
    
    或者更简洁地说:

    it('handles Sql errors', function(done) {
      mockSql.setup.query.toRejectWith(new Error('Booom'));
      sut.getPatientNotificationNumbers(id).should.be.rejectedWith(/Booom/);
    });
    

    你到底想测试什么?SQL server或仅是
    中的方法,然后是
    ?如果它只是
    中的方法,那么
    只需将它提取到一个命名函数。还有,你的承诺代码是错误的。我的承诺代码有什么问题?为什么你甚至在那里有一个延迟的?这样我就可以解析来自存根函数的承诺你有什么理由需要异步解析延迟的吗?