Nodejs 测试驱动来学习mongoose

Nodejs 测试驱动来学习mongoose

mongoose-test

this is a test example project for mongoose!

创建项目

express .

使用淘宝的npm源

nrm use taobao

安装依赖包

npm install

添加更多有用依赖

npm install --save mongoose
npm install --save bcrypt

安装服务器自动重载模块

npm install --save-dev supervisor

安装测试模块

mkdir test

npm install --save-dev mocha npm install --save-dev chai npm install --save-dev sinon npm install --save-dev supertest npm install --save-dev zombie

单元测试需要的各个模块说明

  • mocha(Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun.)
  • chai(Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.)
  • sinon(Standalone test spies, stubs and mocks for JavaScript.)
  • zombie (页面事件模拟Zombie.js is a lightweight framework for testing client-side JavaScript code in a simulated environment. No browser required.)
  • supertest(接口测试 Super-agent driven library for testing node.js HTTP servers using a fluent API)

修改package.json

  "scripts": {
		"start": "./node_modules/.bin/supervisor ./bin/www",
  	"test": "./node_modules/.bin/mocha -u tdd"
	},

创建db/user_model.js

此文件里编写用户相关的mongodb操作

  • Schema define
  • virtual attr
  • save pre callback
  • UserSchema.methods
  • UserSchema.statics
  • findOne
  • user hash password with salt
  • getAuthenticated

创建test/user_model.js

测试2个方法

  • #save()
  • #getAuthenticated()

测试代码基本结构

describe('UserModel', function(){
	before(function() {
    // runs before all tests in this block
  })
  after(function(){
    // runs after all tests in this block
  })
  beforeEach(function(){
    // runs before each test in this block
  })
  afterEach(function(){
    // runs after each test in this block
  })

describe(’#save()’, function(){ it(‘should return sang_test2 when user save’, function(done){ 。。。 }) }) })

生命周期说明

  • before
  • after
  • beforeEach
  • afterEach

断言

断言都是单元测试的核心

断言作为Assert类的静态方法。如果一个断言失败,方法的调用不会返回值,并且会报告一个错误。

如果一个测试包含多个断言,那些紧跟失败断言的断言都不会执行,因为此原因,通常每个测试方法最好只有一个断言。每个方法可以无消息调用,也可以是带有一个简单文本消息调用,或者带有一个消息以及参数调用。在最后一种情况下,使用了一个提供的文本以及参数来格式化消息。

目前流行的断言基本分为3类

  • assert风格
  • should风格
  • expect风格

没有好坏之分,只是看个人习惯

这里使用chai这个库,它支持3种风格的断言,非常方便

Chai has several interfaces that allow the developer to choose the most comfortable. The chain-capable BDD styles provide an expressive language & readable style, while the TDD assert style provides a more classical feel.

var assert = require('chai').assert;
var expect = require('chai').expect;
require('chai').should();

具体用法请查看http://chaijs.com/文档

测试命令

启动mongodb服务

mongod

服务器启动

npm start

测试

npm test

测试相关网址

更多

下面概念,请自行了解

  • TDD
  • BDD

代码: https://github.com/nodeonly/mongoose-test

欢迎拍砖

欢迎关注我的公众号【node全栈】 node全栈.png


10 回复

Nodejs 测试驱动来学习mongoose

介绍

本教程旨在通过测试驱动开发(TDD)的方式帮助大家理解和掌握mongoose,一个强大的Node.js对象数据建模(ODM)库,用于与MongoDB数据库进行交互。

创建项目

首先,我们需要创建一个新的Express项目:

express .

使用淘宝的npm源

为了加快依赖包的下载速度,我们可以切换到淘宝的npm源:

nrm use taobao

安装依赖包

接下来,安装基础的依赖包:

npm install

然后安装必要的库:

npm install --save mongoose
npm install --save bcrypt

安装服务器自动重载模块,以便在代码改变时自动重启服务器:

npm install --save-dev supervisor

安装测试相关的库:

npm install --save-dev mocha
npm install --save-dev chai
npm install --save-dev sinon
npm install --save-dev supertest
npm install --save-dev zombie

修改package.json

package.json中添加启动和测试脚本:

"scripts": {
    "start": "./node_modules/.bin/supervisor ./bin/www",
    "test": "./node_modules/.bin/mocha -u tdd"
}

创建db/user_model.js

在这个文件中定义用户模型:

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema({
    username: { type: String, unique: true, required: true },
    password: { type: String, required: true }
});

UserSchema.virtual('isAuthenticated').get(function() {
    return this.password.length > 0;
});

UserSchema.pre('save', async function(next) {
    const user = this;
    if (!user.isModified('password')) return next();
    try {
        const salt = await bcrypt.genSalt(10);
        user.password = await bcrypt.hash(user.password, salt);
        next();
    } catch (error) {
        next(error);
    }
});

module.exports = mongoose.model('User', UserSchema);

创建test/user_model.js

在这个文件中编写测试代码:

const mongoose = require('mongoose');
const User = require('../db/user_model');
const chai = require('chai');
const should = chai.should();

describe('User Model', function() {
    before(async function() {
        await mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useUnifiedTopology: true });
    });

    after(async function() {
        await mongoose.disconnect();
    });

    describe('#save()', function() {
        it('should return the saved user', async function() {
            const newUser = new User({ username: 'testuser', password: 'testpassword' });
            const savedUser = await newUser.save();
            savedUser.username.should.equal('testuser');
        });
    });

    describe('#getAuthenticated()', function() {
        it('should return true if password is set', async function() {
            const user = new User({ username: 'testuser', password: 'testpassword' });
            const isAuthenticated = await user.getAuthenticated();
            isAuthenticated.should.be.true;
        });
    });
});

运行测试

启动MongoDB服务:

mongod

启动服务器:

npm start

运行测试:

npm test

总结

以上就是使用测试驱动的方式来学习mongoose的基本步骤。通过这种方式,我们不仅能够更好地理解mongoose的功能,还能确保代码的质量。希望这个教程对你有所帮助!


todo

  • 骨架生成脚本
  • 自动测试gulp
  • 代码测试覆盖率
  • 其他测试(集成测试等)补齐

自动测试gulp和代码测试覆盖率

  • auto test
  • 代码测试覆盖率
npm install --save-dev gulp
npm install --save-dev gulp-mocha
npm install --save-dev gulp-istanbul

创建gulpfilejs

var gulp = require('gulp');
var istanbul = require('gulp-istanbul');
var mocha = require('gulp-mocha'); 

gulp.task(‘test’, function (cb) { gulp.src([‘db/**/.js’]) .pipe(istanbul()) // Covering files .on(‘finish’, function () { gulp.src(['test/.js’]) .pipe(mocha()) .pipe(istanbul.writeReports()) // Creating the reports after tests runned .on(‘end’, cb); }); });

gulp.task(‘default’,[‘test’], function() { gulp.watch([’./db//*’,’./test//*’], [‘test’]); });

gulp.task(‘watch’,[‘test’], function() { gulp.watch([’./db//*’,’./test//*’], [‘test’]); });

测试

node_modules/.bin/gulp 

这时,你试试修改测试或源文件试试,看看会不会自动触发测试

当然,如果你喜欢只是测试一次,可以这样做

node_modules/.bin/gulp test 

如果你不熟悉gulp,可以再这里https://github.com/i5ting/js-tools-best-practice/blob/master/doc/Gulp.md学习

如果对测试不太了解,可以看看alsotang的教程 https://github.com/alsotang/node-lessons/tree/master/lesson6

扒出来的好东西

    "test": "./node_modules/.bin/mocha --reporter spec",
    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot",
    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot"

测试覆盖率和ci这样写确实很简单

挖坟。。 其实我想说,这跟mongoose有嘛关系?

先赞一个,留着好好学习

抱着学习mongoose的心态点进来= =结果发现是学习tdd的好东西- -意外收获~~~~

为了使用测试驱动的方式来学习Mongoose,我们可以按照以下步骤进行:

创建项目

首先,使用Express创建一个基础项目:

express .

安装依赖

使用淘宝的npm源加速下载:

nrm use taobao

安装基础依赖:

npm install

安装额外有用的依赖:

npm install --save mongoose bcrypt

安装开发依赖:

npm install --save-dev supervisor mocha chai sinon supertest zombie

修改 package.json

配置启动和测试脚本:

"scripts": {
  "start": "./node_modules/.bin/supervisor ./bin/www",
  "test": "./node_modules/.bin/mocha -u tdd"
}

编写模型文件

创建 db/user_model.js 文件,定义用户模型:

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema({
  username: { type: String, unique: true },
  password: String,
});

UserSchema.pre('save', async function(next) {
  const user = this;
  if (user.isModified('password')) {
    user.password = await bcrypt.hash(user.password, 8);
  }
  next();
});

UserSchema.methods.getAuthenticated = function(password) {
  return bcrypt.compare(password, this.password);
};

module.exports = mongoose.model('User', UserSchema);

编写测试文件

创建 test/user_model.js 文件,编写测试用例:

const mongoose = require('mongoose');
const User = require('../db/user_model');
const { expect } = require('chai');

describe('UserModel', function () {
  before(async function () {
    await mongoose.connect('mongodb://localhost/testdb', { useNewUrlParser: true, useUnifiedTopology: true });
  });

  after(async function () {
    await mongoose.disconnect();
  });

  beforeEach(async function () {
    await User.deleteMany({});
  });

  describe('#save()', function () {
    it('should return the saved user', async function () {
      const user = new User({ username: 'testuser', password: 'testpass' });
      await user.save();
      expect(user.username).to.equal('testuser');
    });
  });

  describe('#getAuthenticated()', function () {
    it('should return true for correct password', async function () {
      const user = new User({ username: 'testuser', password: 'testpass' });
      await user.save();
      const isAuthenticated = await user.getAuthenticated('testpass');
      expect(isAuthenticated).to.be.true;
    });

    it('should return false for incorrect password', async function () {
      const user = new User({ username: 'testuser', password: 'testpass' });
      await user.save();
      const isAuthenticated = await user.getAuthenticated('wrongpass');
      expect(isAuthenticated).to.be.false;
    });
  });
});

运行测试

启动MongoDB服务:

mongod

启动服务器:

npm start

运行测试:

npm test

通过以上步骤,你可以使用测试驱动的方式学习Mongoose。

回到顶部