Javascript Node.js:摩卡咖啡有问题,希望是.throwerr

Javascript Node.js:摩卡咖啡有问题,希望是.throwerr,javascript,node.js,tdd,mocha.js,Javascript,Node.js,Tdd,Mocha.js,我正在尝试为Node构建一个简单的登录模块。我正试图用TDD的方式来做,但我对它还是新手,所以任何能帮助我更好理解它的技巧或资源都会很好 当我查询一个包含无效数据的数据库时,我的问题就出现了,我希望出现一个错误。如果我手动测试应用程序,就会抛出错误-这很好。然而,当我尝试用Mocha和Expect.js测试它时,我得到错误:expected fn抛出异常。如果我将代码从切换到.throwError()到切换到.not.throwError(),则会正确抛出错误。我认为问题是在我尝试异步测试和错误

我正在尝试为Node构建一个简单的登录模块。我正试图用TDD的方式来做,但我对它还是新手,所以任何能帮助我更好理解它的技巧或资源都会很好

当我查询一个包含无效数据的数据库时,我的问题就出现了,我希望出现一个错误。如果我手动测试应用程序,就会抛出错误-这很好。然而,当我尝试用Mocha和Expect.js测试它时,我得到
错误:expected fn抛出异常。如果我将代码从
切换到.throwError()
切换到.not.throwError()
,则会正确抛出错误。我认为问题是在我尝试异步测试和错误处理时出现的。第一次测试顺利通过

谢谢你看

基于塞巴斯蒂安指令的新代码

var MongoClient = require('mongodb').MongoClient;

exports.login = function(callback, email, password) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');

                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            //callback(null, item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                console.log('catch error here');
                callback(err, null);
            } finally {
                console.log('finally here');
                callback(null, item);
            }

            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        expect(function() {
            login.login(function(err, item) {
                //console.log(item);
                if (err) throw err;

                done();
            }, 'email', 'password')
        }).to.not.throwError();
    });
    it('should error on unfound email', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                if (err) throw err;
                done();
            }, 'ert','wqew')
        }).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                throw err;
                done();
            }, 'email','wqew')
        }).to.throwError();
    });
});
var MongoClient = require('mongodb').MongoClient;

exports.login = function(email, password, callback, errCallback) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');
                    errCallback(err);
                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            callback(item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                errCallback(err);
            }
            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        assert.doesNotThrow(function() {
            login.login('email','password',function() {
                done();
            }, function(err) {
                if (err) throw err;
                done();
            });
        });
    });
    it('should error on unfound email', function(done) {
        expect( function() { 
            login.login('atreq','a', function() {
                console.log('true');        
            }, function(err) {
                console.log(err);
                throw err;
        })}).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login('email','apassword', function() {
                console.log('true');
                done();
            }, function(err) {
                console.log(err);
                throw err;
            })
        }).to.throwError();
    });
});
login.js

var MongoClient = require('mongodb').MongoClient;

exports.login = function(callback, email, password) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');

                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            //callback(null, item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                console.log('catch error here');
                callback(err, null);
            } finally {
                console.log('finally here');
                callback(null, item);
            }

            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        expect(function() {
            login.login(function(err, item) {
                //console.log(item);
                if (err) throw err;

                done();
            }, 'email', 'password')
        }).to.not.throwError();
    });
    it('should error on unfound email', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                if (err) throw err;
                done();
            }, 'ert','wqew')
        }).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                throw err;
                done();
            }, 'email','wqew')
        }).to.throwError();
    });
});
var MongoClient = require('mongodb').MongoClient;

exports.login = function(email, password, callback, errCallback) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');
                    errCallback(err);
                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            callback(item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                errCallback(err);
            }
            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        assert.doesNotThrow(function() {
            login.login('email','password',function() {
                done();
            }, function(err) {
                if (err) throw err;
                done();
            });
        });
    });
    it('should error on unfound email', function(done) {
        expect( function() { 
            login.login('atreq','a', function() {
                console.log('true');        
            }, function(err) {
                console.log(err);
                throw err;
        })}).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login('email','apassword', function() {
                console.log('true');
                done();
            }, function(err) {
                console.log(err);
                throw err;
            })
        }).to.throwError();
    });
});
测试/登录测试.js

var MongoClient = require('mongodb').MongoClient;

exports.login = function(callback, email, password) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');

                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            //callback(null, item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                console.log('catch error here');
                callback(err, null);
            } finally {
                console.log('finally here');
                callback(null, item);
            }

            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        expect(function() {
            login.login(function(err, item) {
                //console.log(item);
                if (err) throw err;

                done();
            }, 'email', 'password')
        }).to.not.throwError();
    });
    it('should error on unfound email', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                if (err) throw err;
                done();
            }, 'ert','wqew')
        }).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                throw err;
                done();
            }, 'email','wqew')
        }).to.throwError();
    });
});
var MongoClient = require('mongodb').MongoClient;

exports.login = function(email, password, callback, errCallback) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');
                    errCallback(err);
                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            callback(item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                errCallback(err);
            }
            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        assert.doesNotThrow(function() {
            login.login('email','password',function() {
                done();
            }, function(err) {
                if (err) throw err;
                done();
            });
        });
    });
    it('should error on unfound email', function(done) {
        expect( function() { 
            login.login('atreq','a', function() {
                console.log('true');        
            }, function(err) {
                console.log(err);
                throw err;
        })}).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login('email','apassword', function() {
                console.log('true');
                done();
            }, function(err) {
                console.log(err);
                throw err;
            })
        }).to.throwError();
    });
});
旧代码

login.js

var MongoClient = require('mongodb').MongoClient;

exports.login = function(callback, email, password) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');

                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            //callback(null, item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                console.log('catch error here');
                callback(err, null);
            } finally {
                console.log('finally here');
                callback(null, item);
            }

            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        expect(function() {
            login.login(function(err, item) {
                //console.log(item);
                if (err) throw err;

                done();
            }, 'email', 'password')
        }).to.not.throwError();
    });
    it('should error on unfound email', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                if (err) throw err;
                done();
            }, 'ert','wqew')
        }).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                throw err;
                done();
            }, 'email','wqew')
        }).to.throwError();
    });
});
var MongoClient = require('mongodb').MongoClient;

exports.login = function(email, password, callback, errCallback) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');
                    errCallback(err);
                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            callback(item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                errCallback(err);
            }
            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        assert.doesNotThrow(function() {
            login.login('email','password',function() {
                done();
            }, function(err) {
                if (err) throw err;
                done();
            });
        });
    });
    it('should error on unfound email', function(done) {
        expect( function() { 
            login.login('atreq','a', function() {
                console.log('true');        
            }, function(err) {
                console.log(err);
                throw err;
        })}).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login('email','apassword', function() {
                console.log('true');
                done();
            }, function(err) {
                console.log(err);
                throw err;
            })
        }).to.throwError();
    });
});
测试/登录测试.js

var MongoClient = require('mongodb').MongoClient;

exports.login = function(callback, email, password) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');

                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            //callback(null, item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                console.log('catch error here');
                callback(err, null);
            } finally {
                console.log('finally here');
                callback(null, item);
            }

            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        expect(function() {
            login.login(function(err, item) {
                //console.log(item);
                if (err) throw err;

                done();
            }, 'email', 'password')
        }).to.not.throwError();
    });
    it('should error on unfound email', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                if (err) throw err;
                done();
            }, 'ert','wqew')
        }).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login(function(err, item) {
                console.log(err);
                throw err;
                done();
            }, 'email','wqew')
        }).to.throwError();
    });
});
var MongoClient = require('mongodb').MongoClient;

exports.login = function(email, password, callback, errCallback) {

    MongoClient.connect("mongodb://localhost:27017/stockalertDev", function(err, db) {
        if (err) {

            return err;
        }

        var collection = db.collection('users');
        if (email) {
            collection.findOne({email:email}, function(err, item) {
            try {   
                if (err) {
                    console.log('error');
                    throw new Error('error finding email');
                    errCallback(err);
                } else {

                        if (item) {
                            if (item.password == password) {
                            console.log('logged in');
                            callback(item);
                            //return item;
                            } else {
                                console.log('here');
                                throw new Error('Email and password not matching');
                            }
                        } else {
                            throw new Error('Email not found');
                        }
                    } 
            } catch (err) {
                errCallback(err);
            }
            });
        }

    });
}
var expect = require('expect.js'),
    assert = require('assert'),
    mocha = require('mocha'),
    mongo = require('mongodb');


var login = require('../login');

describe('login', function() {
    it('should login a real user', function(done) {
        assert.doesNotThrow(function() {
            login.login('email','password',function() {
                done();
            }, function(err) {
                if (err) throw err;
                done();
            });
        });
    });
    it('should error on unfound email', function(done) {
        expect( function() { 
            login.login('atreq','a', function() {
                console.log('true');        
            }, function(err) {
                console.log(err);
                throw err;
        })}).to.throwError();

    }); 
    it('should error on incorrect match', function(done) {
        expect(function() {
            login.login('email','apassword', function() {
                console.log('true');
                done();
            }, function(err) {
                console.log(err);
                throw err;
            })
        }).to.throwError();
    });
});

在异步节点代码中使用实例是个坏主意(至少目前是这样)。有一个叫做的概念可以帮助你,但它是非常实验性的

我建议采用节点方式:保留回调的第一个参数以防出错。小例子:

function getUserData(cb) {
    var userData = // ...
    if (userData === null) {
        cb(new Error('Something bad happend.'));
    } else {
        cb(null, userData)
    }
}
如果您想使用errorCallback,就像您已经使用它一样:

errCallback(new Error('Email not found'));
您可以这样做(大多数测试框架为此提供了帮助方法,但是我不太熟悉Mocha及其模块):


在异步节点代码中使用实例是个坏主意(至少目前是这样)。有一个叫做的概念可以帮助你,但它是非常实验性的

我建议采用节点方式:保留回调的第一个参数以防出错。小例子:

function getUserData(cb) {
    var userData = // ...
    if (userData === null) {
        cb(new Error('Something bad happend.'));
    } else {
        cb(null, userData)
    }
}
如果您想使用errorCallback,就像您已经使用它一样:

errCallback(new Error('Email not found'));
您可以这样做(大多数测试框架为此提供了帮助方法,但是我不太熟悉Mocha及其模块):


谢谢你的回复。我试图按照您的建议重构代码,但我不太确定如何进行测试。我已经用回调作为第一个参数重写了它们,并使用了
if(err)throw err
,但仍然得到了相同的
错误:预期fn会抛出异常。我将用新的代码更新我原来的帖子,就像我解释你的指令一样。非常感谢您的帮助。您仍然在考虑同步抛出方法:)您真正想要测试的是回调的error参数是否为null或错误,具体取决于测试。我在回答中加了一个草稿。但是,我还没有使用过Mocha和expect.js,所以不要指望它能以这种方式工作。这只是一个想法。太棒了-它按照您的建议与
expect(err).to.be.a(Error)
一起工作。非常感谢你的帮助!我欠你一个人情,谢谢你的回复。我试图按照您的建议重构代码,但我不太确定如何进行测试。我已经用回调作为第一个参数重写了它们,并使用了
if(err)throw err
,但仍然得到了相同的
错误:预期fn会抛出异常。我将用新的代码更新我原来的帖子,就像我解释你的指令一样。非常感谢您的帮助。您仍然在考虑同步抛出方法:)您真正想要测试的是回调的error参数是否为null或错误,具体取决于测试。我在回答中加了一个草稿。但是,我还没有使用过Mocha和expect.js,所以不要指望它能以这种方式工作。这只是一个想法。太棒了-它按照您的建议与
expect(err).to.be.a(Error)
一起工作。非常感谢你的帮助!我欠你一个人情。