SlideShare a Scribd company logo
1 of 27
do teste de unidade ao de
integração
Teste de unidade
→ mocha ( $ npm i -D mocha )
→ chai ( $ npm i -D chai )
→ sinon ( $ npm i -D sinon )
$ mkdir -p nodejs-tests/test ; cd nodejs-tests
$ npm init -y
$ touch index.js test/index.test.js
$ npm i -D mocha chai sinon
index.js
exports.sum = (x, y) => x + y;
index.test.js
const assert = require('assert');
const { sum } = require('../index');
describe('Index', () => {
describe('sum()', () => {
it('should return the sum of 2 + 2 that equals 4', () => {
const result = sum(2, 2);
assert.deepEqual(result, 4);
});
});
});
package.json
"scripts": {
"test": "mocha test/**/*.test.js"
}
$ npm test
Index
sum()
✓ should return the sum of 2 + 2 that equals 4
1 passing (13ms)
index.test.js
const { expect } = require('chai');
const { sum } = require('../index');
describe('Index', () => {
describe('sum()', () => {
it('should return the sum of 2 + 2 that equals 4', () => {
expect(sum(2, 2)).to.be.deep.equal(4);
});
});
});
Chai
const should = require('chai').should();
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
tea.should.have.property('flavors')
.with.lengthOf(3);
const { assert } = require('chai');
assert.typeOf(foo, 'string');
assert.equal(foo, 'bar');
assert.lengthOf(foo, 3)
assert.property(tea, 'flavors');
assert.lengthOf(tea.flavors, 3);
Should Assert
class UserService {
constructor(Database) {
this.Database = Database;
}
async findAll() {
try {
const users = await this.Database.findAll();
return users;
} catch (error) {
console.log('Error on find users from database', error);
}
}
}
module.exports = UserService;
const UserService = require('../src/users/user.service');
const { expectedUser } = require('./fixtures/user.json');
describe('UserService', () => {
describe('findAll()', () => {
it('should return all users', async() => {
const fakeDatabase = {
async findAll() {
return [expectedUser];
}
}
const userService = new UserService(fakeDatabase);
const users = await userService.findAll();
expect(users).to.be.eql([expectedUser]);
});
});
});
class UserService {
constructor(Database) {
this.Database = Database;
}
async create(user) {
try {
await this.Database.create(user);
} catch(error) {
console.log('Error on create a new user', error);
}
}
// other methods...
}
module.exports = UserService;
const sinon = require('sinon');
const UserService = require('../src/users/user.service');
const { newUser } = require('./fixtures/user.json');
describe('UserService', () => {
describe('create()', () => {
it('should create a new user', () => {
const fakeDatabase = {
create(user) { }
};
const createSpy = sinon.spy(fakeDatabase, 'create');
const userService = new UserService(fakeDatabase);
userService.create(newUser);
sinon.assert.calledOnce(createSpy);
sinon.assert.calledWith(createSpy, newUser);
createSpy.restore();
});
});
});
const axios = require('axios');
class OrderService {
constructor() {}
async findByUserId(userId) {
try {
const response = await axios.get(`https://api/v1/orders?userId=${userId}`);
return response.data.orders;
} catch(error) {
console.log(`Error on find orders`, error);
}
}
}
module.exports = OrderService;
const sinon = require('sinon');
const axios = require('axios');
const OrderService = require('../src/orders/order.service');
const { orders } = require('./fixtures/orders.json');
describe('OrderService', () => {
describe(`findByUserId(1)`, () => {
it('should return orders from userId 1', async() => {
const userId = 1;
const orderService = new OrderService();
const ordersResponse = { data: { orders: orders } };
const getStub = sinon.stub(axios, 'get');
getStub
.withArgs(`https://api/v1/orders?userId=${userId}`)
.returns(Promise.resolve(ordersResponse));
const response = await orderService.findByUserId(userId);
expect(response).to.be.eql(orders);
getStub.restore();
});
});
});
Teste de integração
→ mocha ( $ npm i -D mocha )
→ chai ( $ npm i -D chai )
→ chai-http ( $ npm i -D chai-http )
→ nock ( $ npm i -D nock )
app.js
const express = require('express');
const bodyParser = require('body-parser');
const userRoutes = require('./users/user.routes');
const database = require('./database');
const app = express();
app.use(bodyParser.json());
app.database = database();
userRoutes(app);
module.exports = app;
helpers.js
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../../src/app');
chai.use(chaiHttp);
global.request = chai.request(app);
global.UserModel = app.database.models.Users;
global.expect = chai.expect;
user.routes.js
const { CREATED } = require('http-status');
const UserService = require('./user.service');
module.exports = (app) => {
const userService = new UserService(app.database.models.Users);
app.post('/users', (req, res) => {
return userService.create(req.body)
.then(() => res.sendStatus(CREATED));
});
app.get('/users', (req, res) => {
return userService.findAll()
.then(users => res.json({ users }));
});
}
const { CREATED } = require('http-status');
const { newUser } = require('./fixtures/user.json');
describe('User routes', () => {
beforeEach(() => UserModel.destroy({ where: {} }));
describe('POST /users', () => {
it('should create a new user', async() => {
const response = await request.post('/users').send(newUser);
const resultSet = await UserModel.findById(newUser.id);
const userCreated = resultSet.toJSON();
expect(response).to.have.status(CREATED);
expect(userCreated).to.be.eql(newUser);
});
});
});
"scripts": {
"test:unit": "mocha --require test/unit/helpers.js test/unit/**/*.test.js",
"test:integration": "mocha --require test/integration/helpers.js test/integration/**/*.test.js --exit",
}
const { CREATED, OK } = require('http-status');
const { newUser, defaultUser } = require('./fixtures/user.json');
describe('User routes', () => {
beforeEach(() => {
return UserModel
.destroy({ where: {} })
.then(() => UserModel.create(defaultUser));
});
describe('GET /users', () => {
it('should return all users', async() => {
const response = await request.get('/users');
expect(response).to.have.status(OK);
expect(response.body.users).to.be.eql([defaultUser]);
});
});
});
const OrderService = require('./order.service');
module.exports = (app) => {
const orderService = new OrderService();
app.get('/orders', (req, res) => {
return orderService.findByUserId(req.query.userId)
.then(orders => res.json({ orders }));
});
}
const { OK } = require('http-status');
const { orders } = require('./fixtures/order.json');
const userId = 1;
describe('Order routes', () => {
beforeEach(() => {
nock('https://api')
.get(`/v1/orders?userId=${userId}`)
.reply(OK, { orders });
});
it(`GET /orders?userId=${userId}`, async() => {
const response = await
request.get(`/orders?userId=${userId}`);
expect(response).to.have.status(OK);
expect(response.body).to.be.eql({ orders });
});
});
Obrigado!
Vinícius Pretto
Software Developer at
vini.prettodasilva@gmail.com
https://github.com/vinicius-pretto/nodejs-automation-tests

More Related Content

What's hot

AngularJS Routing
AngularJS RoutingAngularJS Routing
AngularJS RoutingEyal Vardi
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboardsDenis Ristic
 
AngularJS Compile Process
AngularJS Compile ProcessAngularJS Compile Process
AngularJS Compile ProcessEyal Vardi
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboardsDenis Ristic
 
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! GrailsプラグインTsuyoshi Yamamoto
 
Cервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииCервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииArtem Kovardin
 
The next step, part 2
The next step, part 2The next step, part 2
The next step, part 2Pat Cavit
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Eyal Vardi
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the newRemy Sharp
 
Sprout core and performance
Sprout core and performanceSprout core and performance
Sprout core and performanceYehuda Katz
 
Performance Optimization In Angular 2
Performance Optimization In Angular 2Performance Optimization In Angular 2
Performance Optimization In Angular 2Eyal Vardi
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js FundamentalsMark
 
Understanding Functions and "this" in the World of ES2017+
Understanding Functions and "this" in the World of ES2017+Understanding Functions and "this" in the World of ES2017+
Understanding Functions and "this" in the World of ES2017+Bryan Hughes
 
AngularJS: what is underneath the hood
AngularJS: what is underneath the hood AngularJS: what is underneath the hood
AngularJS: what is underneath the hood DA-14
 

What's hot (20)

AngularJS Routing
AngularJS RoutingAngularJS Routing
AngularJS Routing
 
06 jQuery #burningkeyboards
06 jQuery  #burningkeyboards06 jQuery  #burningkeyboards
06 jQuery #burningkeyboards
 
AngularJS Compile Process
AngularJS Compile ProcessAngularJS Compile Process
AngularJS Compile Process
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
 
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
第4回 g* ワークショップ はじめてみよう! Grailsプラグイン
 
Cервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииCервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегии
 
Pengenalan blaast platform sdk
Pengenalan blaast platform sdkPengenalan blaast platform sdk
Pengenalan blaast platform sdk
 
Coding website
Coding websiteCoding website
Coding website
 
The next step, part 2
The next step, part 2The next step, part 2
The next step, part 2
 
jQuery
jQueryjQuery
jQuery
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the new
 
Sprout core and performance
Sprout core and performanceSprout core and performance
Sprout core and performance
 
Performance Optimization In Angular 2
Performance Optimization In Angular 2Performance Optimization In Angular 2
Performance Optimization In Angular 2
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
Understanding Functions and "this" in the World of ES2017+
Understanding Functions and "this" in the World of ES2017+Understanding Functions and "this" in the World of ES2017+
Understanding Functions and "this" in the World of ES2017+
 
AngularJS: what is underneath the hood
AngularJS: what is underneath the hood AngularJS: what is underneath the hood
AngularJS: what is underneath the hood
 
Introducing jQuery
Introducing jQueryIntroducing jQuery
Introducing jQuery
 

Similar to Nodejs do teste de unidade ao de integração

前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Rntb20200805
Rntb20200805Rntb20200805
Rntb20200805t k
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013Laurent_VB
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silexMichele Orselli
 
TDD in the wild
TDD in the wildTDD in the wild
TDD in the wildBrainhub
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptRyan Anklam
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015Fernando Daciuk
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 

Similar to Nodejs do teste de unidade ao de integração (20)

Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Express JS
Express JSExpress JS
Express JS
 
Rntb20200805
Rntb20200805Rntb20200805
Rntb20200805
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
TDD in the wild
TDD in the wildTDD in the wild
TDD in the wild
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 

Recently uploaded

Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 

Recently uploaded (20)

Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 

Nodejs do teste de unidade ao de integração

  • 1. do teste de unidade ao de integração
  • 2.
  • 3. Teste de unidade → mocha ( $ npm i -D mocha ) → chai ( $ npm i -D chai ) → sinon ( $ npm i -D sinon )
  • 4. $ mkdir -p nodejs-tests/test ; cd nodejs-tests $ npm init -y $ touch index.js test/index.test.js $ npm i -D mocha chai sinon
  • 6. index.test.js const assert = require('assert'); const { sum } = require('../index'); describe('Index', () => { describe('sum()', () => { it('should return the sum of 2 + 2 that equals 4', () => { const result = sum(2, 2); assert.deepEqual(result, 4); }); }); });
  • 8. $ npm test Index sum() ✓ should return the sum of 2 + 2 that equals 4 1 passing (13ms)
  • 9. index.test.js const { expect } = require('chai'); const { sum } = require('../index'); describe('Index', () => { describe('sum()', () => { it('should return the sum of 2 + 2 that equals 4', () => { expect(sum(2, 2)).to.be.deep.equal(4); }); }); });
  • 10. Chai const should = require('chai').should(); foo.should.be.a('string'); foo.should.equal('bar'); foo.should.have.lengthOf(3); tea.should.have.property('flavors') .with.lengthOf(3); const { assert } = require('chai'); assert.typeOf(foo, 'string'); assert.equal(foo, 'bar'); assert.lengthOf(foo, 3) assert.property(tea, 'flavors'); assert.lengthOf(tea.flavors, 3); Should Assert
  • 11. class UserService { constructor(Database) { this.Database = Database; } async findAll() { try { const users = await this.Database.findAll(); return users; } catch (error) { console.log('Error on find users from database', error); } } } module.exports = UserService;
  • 12. const UserService = require('../src/users/user.service'); const { expectedUser } = require('./fixtures/user.json'); describe('UserService', () => { describe('findAll()', () => { it('should return all users', async() => { const fakeDatabase = { async findAll() { return [expectedUser]; } } const userService = new UserService(fakeDatabase); const users = await userService.findAll(); expect(users).to.be.eql([expectedUser]); }); }); });
  • 13. class UserService { constructor(Database) { this.Database = Database; } async create(user) { try { await this.Database.create(user); } catch(error) { console.log('Error on create a new user', error); } } // other methods... } module.exports = UserService;
  • 14. const sinon = require('sinon'); const UserService = require('../src/users/user.service'); const { newUser } = require('./fixtures/user.json'); describe('UserService', () => { describe('create()', () => { it('should create a new user', () => { const fakeDatabase = { create(user) { } }; const createSpy = sinon.spy(fakeDatabase, 'create'); const userService = new UserService(fakeDatabase); userService.create(newUser); sinon.assert.calledOnce(createSpy); sinon.assert.calledWith(createSpy, newUser); createSpy.restore(); }); }); });
  • 15. const axios = require('axios'); class OrderService { constructor() {} async findByUserId(userId) { try { const response = await axios.get(`https://api/v1/orders?userId=${userId}`); return response.data.orders; } catch(error) { console.log(`Error on find orders`, error); } } } module.exports = OrderService;
  • 16. const sinon = require('sinon'); const axios = require('axios'); const OrderService = require('../src/orders/order.service'); const { orders } = require('./fixtures/orders.json'); describe('OrderService', () => { describe(`findByUserId(1)`, () => { it('should return orders from userId 1', async() => { const userId = 1; const orderService = new OrderService(); const ordersResponse = { data: { orders: orders } }; const getStub = sinon.stub(axios, 'get'); getStub .withArgs(`https://api/v1/orders?userId=${userId}`) .returns(Promise.resolve(ordersResponse)); const response = await orderService.findByUserId(userId); expect(response).to.be.eql(orders); getStub.restore(); }); }); });
  • 17. Teste de integração → mocha ( $ npm i -D mocha ) → chai ( $ npm i -D chai ) → chai-http ( $ npm i -D chai-http ) → nock ( $ npm i -D nock )
  • 18. app.js const express = require('express'); const bodyParser = require('body-parser'); const userRoutes = require('./users/user.routes'); const database = require('./database'); const app = express(); app.use(bodyParser.json()); app.database = database(); userRoutes(app); module.exports = app;
  • 19.
  • 20. helpers.js const chai = require('chai'); const chaiHttp = require('chai-http'); const app = require('../../src/app'); chai.use(chaiHttp); global.request = chai.request(app); global.UserModel = app.database.models.Users; global.expect = chai.expect;
  • 21. user.routes.js const { CREATED } = require('http-status'); const UserService = require('./user.service'); module.exports = (app) => { const userService = new UserService(app.database.models.Users); app.post('/users', (req, res) => { return userService.create(req.body) .then(() => res.sendStatus(CREATED)); }); app.get('/users', (req, res) => { return userService.findAll() .then(users => res.json({ users })); }); }
  • 22. const { CREATED } = require('http-status'); const { newUser } = require('./fixtures/user.json'); describe('User routes', () => { beforeEach(() => UserModel.destroy({ where: {} })); describe('POST /users', () => { it('should create a new user', async() => { const response = await request.post('/users').send(newUser); const resultSet = await UserModel.findById(newUser.id); const userCreated = resultSet.toJSON(); expect(response).to.have.status(CREATED); expect(userCreated).to.be.eql(newUser); }); }); });
  • 23. "scripts": { "test:unit": "mocha --require test/unit/helpers.js test/unit/**/*.test.js", "test:integration": "mocha --require test/integration/helpers.js test/integration/**/*.test.js --exit", }
  • 24. const { CREATED, OK } = require('http-status'); const { newUser, defaultUser } = require('./fixtures/user.json'); describe('User routes', () => { beforeEach(() => { return UserModel .destroy({ where: {} }) .then(() => UserModel.create(defaultUser)); }); describe('GET /users', () => { it('should return all users', async() => { const response = await request.get('/users'); expect(response).to.have.status(OK); expect(response.body.users).to.be.eql([defaultUser]); }); }); });
  • 25. const OrderService = require('./order.service'); module.exports = (app) => { const orderService = new OrderService(); app.get('/orders', (req, res) => { return orderService.findByUserId(req.query.userId) .then(orders => res.json({ orders })); }); }
  • 26. const { OK } = require('http-status'); const { orders } = require('./fixtures/order.json'); const userId = 1; describe('Order routes', () => { beforeEach(() => { nock('https://api') .get(`/v1/orders?userId=${userId}`) .reply(OK, { orders }); }); it(`GET /orders?userId=${userId}`, async() => { const response = await request.get(`/orders?userId=${userId}`); expect(response).to.have.status(OK); expect(response.body).to.be.eql({ orders }); }); });
  • 27. Obrigado! Vinícius Pretto Software Developer at vini.prettodasilva@gmail.com https://github.com/vinicius-pretto/nodejs-automation-tests