广告 ·ultimatecourses.com
用终极课程学习角度正确的方式“></一种></div>
          <article class=

均值应用程序:服务器

第1部分:REST API使用用Mongoose加上Mocha和Chai测试编写的快递服务器。

系列

This post is part of a series on<一种href="//www.nxtmastery.com/2017/07/16/mean-app-unplugged/">building a MEAN app using TypeScript with Angular Material and Reactive programming

源代码

You can download the source code and follow along or fork the repository on GitHub:

首先,运行GULP任务,然后启动Node.js Express Server。

$湾$chmod.+x ./dist/bin/www $ ./dist/bin/www

然后,serve the Angular client using the CLI:

$ng serve

Goals

Our goals for this series are:

  1. 创建一个类似于Angular的英雄教程应用程序的简单CRUD应用程序。
  2. 使用用猫源编写的Express创建REST API,以便持续到MongoDB。
  3. 为UI使用角度材料和角度柔性布局。
  4. 使用JavaScript的反应扩展,特别是RXJS和NGRX。

在此帖子中,我们将首先使用类型标注中编写的Express构建REST API。

项目结构

Our project will have aclientA.server夹。现在,让我们专注于服务器端。

├──客户├──└──.ts│└──测试│└──英雄└──tsconfig.json

安装节点和NPM

To get started we will create a new project using the Node Package Manager (npm).

如果您没有安装节点,其中包括NPM,我会建议您使用<一种href="http://brew.sh/">家用

</码>$ / usr / bin / ruby​​ -e$(卷曲-fssl https://raw.githubusercontent.com/homebrew/install/master/install.$ Brew Update $ Brew Doctor</ pre.>然后,安装节点using the`brew安装`command: ```bash $ brew安装节点

接下来,使用NPM创建一个新项目。我打电话给项目“卑鄙的材料 - 反应”:

$mkdir意思是材料 - 反应cd意思是材料 - 反应npminit

按照提示进行操作以创建新项目。此时,您的项目应包含单个package.json.file.

Install Gulp

下一步是安装GULP,我们将使用它来自动化我们的工作流程。我们还将安装我们需要的几个插件:

$npm安装GULP-CLI -G $npm安装GULP --SAVE-DEV $npm安装类型script --save-dev $npm安装del --save-dev $npm安装湾-sourcemaps --save-dev $npm安装GULP-TypeScript.- 保存-dev $npm安装run-sequence --save-dev $npm安装ts-node --save-dev $触摸gulpfile.js.$触摸湾file.ts

Note the use of the<码>- 保存-dev标志,指示NPM将开发依赖性写入我们的项目package.json.file.

以下是我们使用的插件的快速破坏:

  • del- 删除所有文件distdirectory.
  • 湾-sourcemaps- creates inline source maps.
  • GULP-TypeScript.- 将TypeScript编译为JS。
  • run-sequence- 使我们能够以特定顺序运行一系列GULP任务。
  • ts-node- 使我们能够在节点中执行打字代码。

另请注意,我创建了两个空文件;该gulpfile.js.file will usets-nodeto execute the湾file.ts打字文件。

Here is what thegulpfile.js.file will contain:

要求'ts-node'寄存器{项目false禁用真正};要求'./gulpfile.ts';

让我们开始构建湾file.tsfile. We will start by created two tasks:

  1. clean- will delete our distributable directories.
  2. build:express- will build our Express HTTP server.

We will also create adefault将使用的任务run-sequenceplugin to execute a series of Gulp tasks.

这只是我们的墨水湾任务的开始。我们将在建立我们的应用程序时建立更多。

const=要求'gulp'del=要求'del'runsequence.=要求'运行序列'sourcemaps.=要求'gulp-sourcemaps'TSC.=要求'gulp-typescript';/ ** *删除dist目录。* /任务'clean'done=>{返回del['dist']done;};/ ** *复制开始脚本。* /任务'copy'=>{返回SRC.'服务器/ bin / *'Dest.'dist/bin';};/***Build the server. */任务'构建:Express'=>{const项目=TSC.createProject'server / tsconfig.json';const结果=SRC.'server/src/**/*.ts'sourcemaps.init项目;返回结果jssourcemaps.Dest.'dist / server';};/ ** *构建项目。* /任务'default'done=>{runsequence.'clean''copy''构建:Express';};

如果您尝试在项目目录中执行Gulp,则应收到错误。这是因为我们尚未安装Express并通过Server代码通过tsconfig.json.file. Let's do that.

Install Express

接下来,让我们安装Express:

$npm安装Express --save.

Note the<码>- 保存flag. This will save a production dependency in thepackage.json.file.

Next, let's set up our server folder structure:

$mkdirserver $cdserver $触摸tsconfig.json.

然后,修改tsconfig.json.file that will contain the server's TypeScript configuration:

{“compileroptions”{“目标”“es5"“模块”“commonjs”“调节化学”“节点““sourcemap”真正“emitdecoratormetadata”真正“experimentalDecorators"真正“lib"[“es2015"“dom”]“noImplicitAny"真正“suppressimplicitanyindexerrors”真正“类型Roots"[“../node_modules/@types/”]}“compileOnSave"真正“exclude"[“节点_modules/*"]}

If you are not familiar with the TypeScript compiler options and using thetsconfig.json.file, check out<一种href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html">tsconfig.json上的文档

服务器启动脚本

Next we need to create our Express HTTP server start script:

$mkdirSRC $mkdir班$cdSRC./班$触摸万维网

这是完整内容的万维网file:

!!/usr./bin/env.节点'使用strict';//module dependenciesvarserver=要求'../server/server';vardebug=要求'debug''express:server';varhttp.=要求'http';//create http servervarhttpport.=unconizeport.processenv.港口||8080;var一种pp=server服务器bootstrap一种pp;一种ppset'港口'httpport.;varhttp.服务器=http.CreateServer一种pp;//列出en on provided portshttp.服务器列出enhttpport.;//一种dd error handlerhttp.服务器'error'onerror.;//开始在港口收听http.服务器“听”onlistening.;/***Normalize a port into a number, string, or false. */功能unconizeport.{var港口=parseInt10.;ifisnan.港口{//命名为管道返回;}if港口>=0.{//端口号返回港口;}返回false;}/ ** * HTTP服务器的事件侦听器“错误”事件。* /功能onerror.呃or{if呃orsyscall!!=='听'{呃or;}varbind=类型of港口==='string''管道'+港口'港口 '+港口;//使用友好的消息处理特定的侦听错误开关呃or{case'EACCES'安慰呃orbind+' requires elevated privileges';process出口1;break;case'eaddrinuse'安慰呃orbind+' is already in use';process出口1;break;default呃or;}}/***Event listener for HTTP server "listening" event. */功能onlistening.{var一种ddr=http.服务器地址;varbind=类型of一种ddr==='string''pipe '+一种ddr'port '+一种ddr港口;debug'Listening on '+bind;}

This start script was slightly modified by an example on the Google Cloud Platform developer website, so I take not credit for it. This will create our HTTP server on the default port of 8080. You can customize this to run on the standard HTTP port 80 in production.

接下来,我们需要修改允许的权限万维网文件以便我们可以执行它:

$chmod.+ x www.

安装中间件

该first step of using Express is to install and configure all of the middleware that our application needs. Let's install these via npm:

$npm安装Body-Parser --Save $npm安装摩根- 保存$npm安装ErrorHandler.- 保存

然后,we need to install the TypeScript declaration files for each:

$npm安装@类型/ body-parser --save-dev $npm安装@ types / morgan --save-dev $npm安装@types/errorhandler --save-dev

Here's a quick rundown of each of these and what they do:

  • 身体-parser- parses JSON and URL encoded data into the<码>身体属性of the<码>请求目的。
  • 摩根- 记录所有HTTP请求。
  • ErrorHandler.- a development-only error handler for debugging.

服务器Class

Let's start building out the<码>服务器class:

import*一种sBodyParser.from“身体-parser";import*一种s表现from“表现“;import*一种s摩根from“摩根”;import*一种spathfrom“路径”;import呃orHandler=要求“ErrorHandler”;import猫鼬=要求“猫鼬”;/***该服务器。**@class Server */出口class服务器{/ ** *快递申请。* @type {application} * /public一种pp表现一种pplication;/***Bootstrap the application. * @static */publicstaticbootstrap服务器{返回服务器;}/***@constructor */构造函数{//create expressjs application这个一种pp=表现;//configure application这个config;//一种dd api这个一种pi;}/***Create REST API routes * * @class Server */public一种pi{//现在空了}/ ** *配置应用程序* * @class服务器* /publicconfig{//摩根middleware to log HTTP requests这个一种pp采用摩根“dev";//采用json form parser middlware这个一种pp采用BodyParser.json;//采用query string parser middlware这个一种pp采用BodyParser.urlencoded{延长真正};//连接to mongoose猫鼬连接“MongoDB.://localhost:27017/mean-material-reactive";猫鼬连接“呃or"呃or=>{安慰呃or呃or;};//catch 404 and forward to error handler这个一种pp采用功能任何表现请求res.表现Responsenext表现NextFunction{status=404.;next;};//呃or handling这个一种pp采用呃orHandler;}}

Some things to note:

  • 首先,我们导入我们需要的所有中间件和依赖项。注意,我正在进口猫鼬,但我们还没有安装它。我们很快就会到达那么。
  • Next, I defined our<码>服务器class.
  • 然后,我有一个名为的公共财产<码>一种pp这将存储对运行的快递应用程序的引用。
  • 静态<码>bootstrap()method will instantiate a new instance of the<码>服务器并返回它。
  • 该<码>构造函数()功能creates a new express application, and then invokes the<码>config()和<码>一种pi()methods.
  • 现在,<码>一种pi()method is left empty. This is where we will build out each REST API endpoint.
  • 该<码>config()method wires up all of the middleware with our app, as well as the mongoose connection. I have a string constant in my code example for connecting to MongoDb. This is just for demo purposes. I would suggest a more robust solution for storing the connection string in a production application.

安装MongoDB和Mongoose

该next step is to install MongoDB. We'll be using Homebrew to do this (we already installed Homebrew above in order to install Node).

$brew安装MongoDB.$LN.-sfv /usr/local/opt/mongodb/*.plist ~/Library/LaunchAgents

该second command above will enable MongoDb to start when your system starts. This is handy for your development enviroment.

现在,使用NPM安装Mongoose:

$npm安装猫鼬- 保存$npm安装@ types / mongoose --save-dev $npm安装@types/mongodb --save-dev

Note that I have also installed the TypeScript declaration files for both mongoose as well as MongoDb.

Define Interface

该next step is to define our application's interfaces. For this tutorial I am going to have a single<码>Hero接口。

First, create theserver/src/interfaces目录以及一个英雄file:

$mkdir接口s $cd接口s $触摸英雄

Here is the very simply interface for our<码>Hero

出口接口Hero{namestring;}

Our<码>Hero上ly has a single<码>string属性:<码>name

定义架构

下一步是为我们的模型定义模式。创建一个新的server/src/schemas目录以及一个英雄file:

$mkdir架构美元cd架构美元触摸英雄

然后,define the schema in英雄

import{Schema}from'猫鼬';出口varheroSchemaSchema=Schema{创造{类型DatedefaultDatenow}name};

您可能会注意到,我还包括一个名为的额外的属性<码>创造在我的架构里。这将是一个<码>Datethat tracks when the hero was created, as the default value is<码>DATE.NOW.

Define Model

最后,创建基于我们的接口和架构的模型。创建一个新的server/src/modelsdirectory along with the英雄file:

$mkdir型号$cd型号$触摸英雄

现在,让我们定义我们的模型:

import猫鼬=要求“猫鼬”;import{DocumentModel}from“猫鼬”;import{Hero一种sHeroInterface}from“../interfaces/hero”;import{heroSchema}from“。。/schemas/hero";出口接口her延伸HeroInterfaceDocument{}出口接口herStatic延伸Model<her>{}出口constHero=猫鼬model<herherStatic>“Hero"heroSchema;

Great! We have now defined our<码>Hero接口和associated schema and model for interfacing with MongoDb using Mongoose.

休息API.

该next step is to define a REST API in our Express application. For this tutorial we will only be defining a single REST API endpoint for our heros. Let's start by creating the服务器/ src / apidirectory and a newheros.tsfile:

$mkdir一种pi $cd一种pi $触摸heros.ts

Now, create a new<码>Herosapi.课程将使用REST处理我们的CRUD操作:

// 表现import{NextFunctionResponse请求路由器}from“表现“;//模型import{Hero}from“。。/models/hero";/***@class HerosApi */出口classHerosapi.{/ ** *创建API。* @静态的 */publicstaticcreaterouter路由器{//删除router删除“/heros/:id([0-9a-f]{24})"请求res.ResponsenextNextFunction=>{Herosapi.删除res.next;};//得到routerget“/heros"请求res.ResponsenextNextFunction=>{Herosapi.列出res.next;};routerget“/heros/:id([0-9a-f]{24})"请求res.ResponsenextNextFunction=>{Herosapi.getres.next;};//邮寄router帖子“/heros"请求res.ResponsenextNextFunction=>{Herosapi.createres.next;};//PUTrouterput“/heros/:id([0-9a-f]{24})"请求res.ResponsenextNextFunction=>{Herosapi.更新res.next;};}/ ** *创建一个新的英雄。* @param req {请求}快递请求对象。* @param res {response}快速响应对象。* @param下一个{nextfunction}下一个函数继续。* /publiccreate请求res.ResponsenextNextFunction{//创建英雄consthero=Hero身体;hero保存然后hero=>{res.jsonherotoObject;next;}catchnext;}/***Delete a hero. * @param req {Request} The express request object. * @param res {Response} The express response object. * @param next {NextFunction} The next function to continue. */public删除请求res.ResponsenextNextFunction{//verify the id parameter existsconstparam_id.string=“id";ifparams[param_id.]===undefined{res.sendstatus.404.;next;返回;}//获得ID.constidstring=params[param_id.];//获得英雄HeroFindByid.id然后hero=>{//verify hero existsifhero===空值{res.sendstatus.404.;next;返回;}hero去掉然后=>{res.sendstatus.200.;next;}catchnext;}catchnext;}/ ** *获得英雄。* @param req {请求}快递请求对象。* @param res {response}快速响应对象。* @param下一个{nextfunction}下一个函数继续。* /publicget请求res.ResponsenextNextFunction{//verify the id parameter existsconstparam_id.string=“id";ifparams[param_id.]===undefined{res.sendstatus.404.;next;返回;}//获得ID.constidstring=params[param_id.];//获得英雄HeroFindByid.id然后hero=>{//验证英雄被发现ifhero===空值{res.sendstatus.404.;next;返回;}//send json of hero objectres.jsonherotoObject;next;}catchnext;}/***List all heros. * @param req {Request} The express request object. * @param res {Response} The express response object. * @param next {NextFunction} The next function to continue. */public列出请求res.ResponsenextNextFunction{//获得英雄sHero然后heros=>{res.jsonherosmaphero=>herotoObject;next;}catchnext;}/***Update a hero. * @param req {Request} The express request object. * @param res {Response} The express response object. * @param next {NextFunction} The next function to continue. */public更新请求res.ResponsenextNextFunction{constparam_id.string=“id";//verify the id parameter existsifparams[param_id.]===undefined{res.sendstatus.404.;next;返回;}//获得ID.constidstring=params[param_id.];//获得英雄HeroFindByid.id然后hero=>{//验证英雄被发现ifhero===空值{res.sendstatus.404.;next;返回;}//保存英雄Object一种ssignhero身体保存然后heroher=>{res.jsonherotoObject;next;}catchnext;}catchnext;}}

Some things to note:

  • We first import the necessary classes and interfaces from Express, along with our<码>Heromodel.
  • 静态<码>create()方法需要<码>路由器instance from our<码>服务器类并配置路由/一种pi/herosendpoint.
  • 我们实施以下动词:删除,获取,发布和放置。每个动词都调用了一个适当的方法<码>Herosapi.class.
  • 每种方法都需要表达<码>请求那<码>Response和<码>NextFunction对象。
  • 该re is no authentication or verification happening, meaning our API is open to the public. This is most likely not a good idea for prodution use. I am not including this in this tutorial, but one way to solve this is to have all of your REST API classes extend a<码>BaseApiclass that has an<码>授权()method that verifies your user is authenticated. You may also want to add additional logic in each REST API method for verifying that a user has permission to perform the specific action. For simplicity I am not including this here.
  • 使用Mongoose the data is persisted to the MongoDbHeroscollection.
  • Note that when sending the json result to the client using the<码>res.。json()我首先调用的方法<码>。toObject()对策<码>Document从猫鼬返回。
  • If an exception occurs we simply use the<码>抓住()方法的方法<码>诺言object to invoke the<码>nextmethod.
  • 发送状态代码或json结果到客户端务必调用<码>下一个()

在我们进一步之前,我们需要允许跨原因请求。我们的服务器(Express)和客户端(Angular)将在同一本地计算机上运行,​​而是在不同的端口上运行(在端口8080上的一个端口,Anigular CLI的默认端口为4200),因此我们需要启用CORS。要执行此操作,让我们使用并安装corsmiddleware:

$npm安装cors --save $npm安装@类型/ cors --save-dev

然后,将CORS中间件导入<码>服务器班上server/src/server.ts

import*一种scorsfrom'CORS';

Next, import the<码>Herosapi.班上to our<码>服务器class.

import{Herosapi.}from'./api/heros';

如果你记得,我们离开了<码>一种pi()我们的方法<码>服务器class empty. Now it's finally time to implement this and to wire up our<码>Herosapi.

出口class服务器{//删除代码/***休息API.endpoints. */public一种pi{varrouter=表现路由器;//configure CORSconstcorsOptionscorsCORSOPTIONS.={允许的人[“Origin"“X-Requested-With"“内容类型”“接受”“X-Access-token”]credentials真正methods“GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE"origin“http:// localhost:4200”preflightContinuefalse};router采用corscorsOptions;//根请求routerget“/”表现请求res.表现Responsenext表现NextFunction=>{res.json{一种nnouncement“欢迎来到我们的API。”};next;};//创建API路由Herosapi.createrouter;//wire up the REST API这个一种pp采用“/一种pi"router;//启用CORS前飞行routeroptions“*“corscorsOptions;}}

几件事要注意:

测试REST API.

We'll be using a testing framework called Mocha, along with Chai for BSD style assertions, and the chai-http plugin. If you haven't caught on already, I'm a huge TypeScript fan. So, we'll also be using<一种href="https://github.com/PanayotCankov/mocha-typescript">Mocha-TypeScript.要使用TypeScript编写我们的测试,并利用一些ES6 / ES2015,如装饰器。

First, let's get things installed via npm:

$npm安装莫卡- 保存-dev $npm安装chai --save-dev $npm安装chai-http --save-dev $npm安装Mocha-TypeScript.- 保存-dev $npm安装@types/mocha --save-dev $npm安装@types/chai --save-dev $npm安装@types/chai-http --save-dev

让我们创造一个server/src/testsdirectory, and aheros.tstest file:

$mkdir测试$cd测试$触摸heros.ts

让我们开始建立我们的测试:

processenv.node_env.=“test";//莫卡import“摩卡”;import{套房test}from“mocha-typescript”;// mongodb.import{对象}from“mongodb”;//serverimport{服务器}from“../服务器”;//模型import{Hero}from“../interfaces/hero”;import{herherStatic}from“。。/models/hero";import{heroSchema}from“。。/schemas/hero";//猫鼬import猫鼬=要求“猫鼬”;//要求http.servervarhttp.=要求“http.“;//要求chai and use should assertionsletchai=要求“chai";chaishould;//configure chai-httpchai采用要求“chai-http";

这是我们在顶部所做的英雄test file:

  • 首先,我们将node_env环境变量设置为“test”。这是良好的做法,尽管我没有做任何运行时转换,但它可以用于No-Op代码或嘲笑。
  • Next, we import the莫卡图书馆。然后,we import the<码>套房和<码>test从中的装饰者Mocha-TypeScript.包。
  • Next, we import the<码>对象class from theMongoDB.包。
  • 接下来,我们导入我们的<码>服务器class.
  • 然后,we import our<码>Hero接口那该<码>her和<码>herStatic课程,最后,<码>heroSchema功能。我们需要这些来配置我们的Mongoose文档进行测试。
  • Next, we import the<码>猫鼬图书馆。
  • Next, we import the Node.js<码>http.。服务器。
  • 然后,we import<码>chai和instruct chai to use should style assertions.
  • Finally, we are using thechai-httpplugin for chai to perform HTTP response assertions.

Now that we have the imports out of the way, let's start to define the<码>HerosTestclass:

@套房classHerosTest{//constantspublicstaticbase_uri.string=“/ api / heros”;//该mongooose connectionpublicstatic连接猫鼬Connection;//英雄模型publicstaticHeroherStatic;//hero documentpublicstaticheroher;//该http.serverpublicstaticserver任何;/ ** *所有钩子之前。* /publicstaticbefore{//连接to MongoDB猫鼬连接“MongoDB.://localhost:27017/mean-material-reactive";HerosTestHero=猫鼬model<herherStatic>“Hero"heroSchema;//create http serverlet港口=8001;let一种pp=服务器bootstrap一种pp;一种ppset“港口“港口;HerosTestserver=http.CreateServer一种pp;HerosTestserver列出en港口;返回HerosTestcreatehero.;}/ ** *追随钩子* /publicstatic{返回HerosTesthero去掉然后=>{返回猫鼬断开;};}/***Create a test hero. */publicstaticcreatehero.诺言<her>{constdataHero={name“yobet外围布莱恩爱”};返回HerosTestHerodata保存然后hero=>{HerosTesthero=hero;};}}

Our<码>HerosTest班级开始走到一起。

  • We defined a test suite using the<码>套房装饰师。
  • 在我们的测试套件内我已经定义了几个静态属性和方法。使用Mocha-TypeScript.我们可以定义静态<码>before()和<码>后()methods that are invoked once; first,<码>before()我们的所有测试都被执行,然后<码>后()一种ll of our test have executed. This enables us to set things up, and then to tear things down.
  • 在静态<码>before()method we first establish a connection to the MongoDb server using<码>猫鼬。连接()。然后,我使用导入创建文档模型<码>her和<码>herStatic我们之前定义的类。
  • Next, we set up our HTTP server and start it.
  • 然后,I create a new hero in the<码>createhero()静态方法。此方法返回一个<码>承诺目的。Note, that I return the Promise object in the<码>before()静态方法也是如此。我从我的测试中返回一个承诺对象,而不是使用摩卡更传统<码>完成()回调方法。我认为这是更清洁的,更容易使用。
  • 在静态<码>后()method I remove my test hero and disconnect from MongoDb.

既然我们有大部分测试设置和配置,让我们开始添加测试:

@套房classHerosTest{//删除代码@testpublic删除{constdataHero={name“To be deleted"};返回HerosTestHerodata保存然后hero=>{返回chai雷uestHerosTestserverdel`${HerosTestbase_uri.}/${hero_ID}`然后res.ponse=>{res.ponseshouldstatus200.;};};}@testpublicget{返回chai雷uestHerosTestserverget`${HerosTestbase_uri.}/${HerosTesthero_ID}`然后res.ponse=>{res.ponseshouldstatus200.;res.ponse身体shouldbe一种“object";res.ponse身体should属性“name"EQL.HerosTestheroname;};}@testpublic列出{返回chai雷uestHerosTestservergetHerosTestbase_uri.然后res.ponse=>{res.ponseshouldstatus200.;res.ponse身体shouldbe一种n“一种rray";res.ponse身体should的长度1;};}@testpublic帖子{constdataHero={name“magneto”};返回chai雷uestHerosTestserver帖子HerosTestbase_uri.senddata然后res.ponse=>{res.ponseshouldstatus200.;res.ponse身体shouldbe一种“object";res.ponse身体should一种属性“_ID”;res.ponse身体should属性“name"EQL.dataname;返回HerosTestHerofindbyidandremove.res.ponse身体_IDexc.;};}@testpublicput{constdataHero={name“Superman"}返回chai雷uestHerosTestserverput`${HerosTestbase_uri.}/${HerosTesthero_ID}`senddata然后res.ponse=>{res.ponseshouldstatus200.;res.ponse身体shouldbe一种“object";res.ponse身体should一种属性“_ID”;res.ponse身体should属性“name"EQL.dataname;};}}

Let's review our tests:

  • 注意,我们使用该测试使用该测试<码>@test装饰师。
  • First, we have a<码>删除()测试。In our delete test we first create a new hero that will be deleted using the REST API. We'll test this by ensuring that our API responds with a200.OKstatus code.
  • 接下来,我们有一个<码>get()测试。This simply GETs our hero (me, haha) that was created in the<码>createhero()执行之前的静态方法。我们验证响应是200个状态,是一个对象,包括一个属性<码>name具有正确的价值。
  • 接下来,我们有一个<码>列表()测试。这只是所有的英雄。我们验证that tehh reponse is a 200 status, is an array, and has a length of 1.
  • 接下来,我们有一个<码>帖子()test to create a new hero. We define the<码>datathat we will POST to the server, and then send the request. We verify that the response is 200, that it is an object, that it contains both the<码>_ID和<码>name属性,那个<码>name属性等于我们在数据中发送的值。最后,我们删除了我们创建并返回该承诺的新英雄。
  • 最后,我们有一个<码>放()test to update our hero. In this test we will update our hero's name. To verify the test was successful we ensure that the response is 200, that it is an object, that it contains both the<码>_ID和<码>name属性,以及该价值<码>name属性等于我们在数据中发送的值。

Let's go ahead and run our tests to ensure that our REST API is working and operational.

Before we can run our tests, we need to create a new task in our湾file.ts。但是,在我们这样做之前,让我们安装湾-mocha包:

$npm安装Gulp-Mocha  - 索德德

现在,让我们为这项新任务添加新任务湾file.ts

任务'测试:Express'=>{SRC.'dist/server/tests'{false}Gulpmocha.;};

现在,添加test:express任务到执行的任务序列default任务:

任务'default'done=>{runsequence.'clean''copy''构建:Express''测试:Express';};

一种t this point we are ready to run gulp in our project:

$湾

You should see a success message indicating that all four tests have passed. Sweet!

均值App Server测试“></p>
            <h2>Review</h2>
            <p>只是为了审查,我们:</p>
            <ul>
             <li>Installed Node and the Node Package Manager (npm).</li>
             <li>Installed gulp and created a workflow to automate the building and testing of our REST API.</li>
             <li>使用NPM我们安装了Express和我们应用程序所需的中间件。</li>
             <li>创建服务器启动脚本以执行我们的HTTP服务器。</li>
             <li>创造了<码>服务器</码>类创建HTTP服务器和REST API。</li>
             <li>Installed MongoDb and Mongoose for data persistence.</li>
             <li>配置了<em>Heros</em>document in Mongoose.</li>
             <li>使用Mocha和Chai安装和创建测试。</li>
            </ul>
            <h2>继续系列</h2>
            <p>我希望你在系列中享受了第一部分<一种href=building a MEAN app using TypeScript with Angular Material and Reactive programming

Next, in part two of the series, we'll<一种href="//www.nxtmastery.com/2017/07/16/mean-app-angular-material/">start building our Angular application using Angular Material

Brian F Love

Hi, I'm Brian. I am interested in TypeScript, Angular and Node.js. I'm married to my best friend Bonnie, I live in Portland and I ski (a lot).