# SuperTest

[supertest- npm 地址](https://www.npmjs.com/package/supertest)

[supertest - github 地址](https://github.com/visionmedia/supertest#readme)

使用可以[superagent](http://github.com/visionmedia/superagent) 可以很容易的进行HTTP断言。

## 关于

该模块的初衷是提供用于测试HTTP的高级抽象，同时仍然允许您使用超级代理提供的低级API（[lower-level API](https://visionmedia.github.io/superagent/)）。

## 入门

通过npm安装，并且作为一个development依赖保存到`composer.json`。

```
npm install supertest --save-dev
```

一旦安装，现在可以通过简单调用`require('supertest');`来引用；

## 例子

您可以传递一个http.Server或者一个Function to request()——如果服务器还没有侦听连接，那么它将被绑定到一个临时端口，因此不需要跟踪端口。

SuperTest 与任何测试框架一起工作，这里是一个不使用任何测试框架的例子：

```javascript
const request = require('supertest');
const express = require('express');

const app = express();

app.get('/user', function(req, res) {
  res.status(200).json({ name: 'john' });
});

request(app)
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });
```

这里有一个mocha的例子，请注意如何直接传递到任何一个`.expect()`调用：

```javascript
describe('GET /user', function() {
  it('respond with json', function(done) {
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);
  });
});
```

上面的语句需要注意的一点是，如果未添加状态代码.（即`.expect(302)`），则SuperTest 现在将任何HTTP错误（除了2XX响应代码之外的任何错误）作为第一个参数发送到回调。

如果您使用的是.end()方法`.expect()`断言，如果失败，则不会抛出，而是将断言作为错误返回到.end()回调。为了使测试用例失败，您需要重新发送或传递 `err`给D`done()`，如下：

```javascript
describe('POST /users', function() {
  it('responds with json', function(done) {
    request(app)
      .post('/users')
      .send({name: 'john'})
      .set('Accept', 'application/json')
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        done();
      });
  });
});
```

你也可以使用promises:

```javascript
describe('GET /users', function() {
  it('responds with json', function() {
    return request(app)
      .get('/users')
      .set('Accept', 'application/json')
      .expect(200)
      .then(response => {
          assert(response.body.email, 'foo@bar.com')
      })
  });
});
```

期望是按照定义的顺序运行的。此特性可用于在执行断言之前修改响应体或头。

```javascript
describe('POST /user', function() {
  it('user.name should be an case-insensitive match for "john"', function(done) {
    request(app)
      .post('/user')
      .send('name=john') // x-www-form-urlencoded upload
      .set('Accept', 'application/json')
      .expect(function(res) {
        res.body.id = 'some fixed id';
        res.body.name = res.body.name.toLowerCase();
      })
      .expect(200, {
        id: 'some fixed id',
        name: 'john'
      }, done);
  });
});
```

你可以用 superagent 做任何的事情，你可以用supertest——例如文件上传！

```javascript
request(app)
.post('/')
.field('name', 'my awesome avatar')
.attach('avatar', 'test/fixtures/avatar.jpg')
```

不必每次都传递应用程序或url，如果正在测试同一主机，则可以简单地用初始化应用程序或url重新分配请求变量，则每个`request.VERB()`调用都会创建一个新的Test。

```javascript
request = request('http://localhost:5555');

request.get('/').expect(200, function(err){
  console.log(err);
});

request.get('/').expect('heya', function(err){
  console.log(err);
});
```

下面是一个Moka的例子，展示了如何坚持一个请求及其cookies：

```javascript
const request = require('supertest');
const should = require('should');
const express = require('express');
const cookieParser = require('cookie-parser');

describe('request.agent(app)', function() {
  const app = express();
  app.use(cookieParser());

  app.get('/', function(req, res) {
    res.cookie('cookie', 'hey');
    res.send();
  });

  app.get('/return', function(req, res) {
    if (req.cookies.cookie) res.send(req.cookies.cookie);
    else res.send(':(')
  });

  const agent = request.agent(app);

  it('should save cookies', function(done) {
    agent
    .get('/')
    .expect('set-cookie', 'cookie=hey; Path=/', done);
  });

  it('should send cookies', function(done) {
    agent
    .get('/return')
    .expect('hey', done);
  });
})
```

文件[ agency.js](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js) 引入了另一个示例。

## API

可以使用任何[ superagent](http://github.com/visionmedia/superagent) 方法，包括`.write()`,`.pipe()`等，并在`.end()`回调中执行断言以满足较低级别的需要。

### .expect(status\[, fn])

断言响应状态代码。

### .expect(status, body\[, fn])

断言响应状态代码和body。

#### .expect(body\[, fn])

用字符串、正则表达式或解析body对象来断言响应`body`text。

### .expect(field, value\[, fn])

用字符串或正则表达式断言header头的`field value`。

### .expect(function(res) {})

传递自定义断言函数。它将给出检查的响应对象。如果检查失败，则抛出错误。

```javascript
request(app)
  .get('/')
  .expect(hasPreviousAndNextKeys)
  .end(done);

function hasPreviousAndNextKeys(res) {
  if (!('next' in res.body)) throw new Error("missing next key");
  if (!('prev' in res.body)) throw new Error("missing prev key");
}
```

### .end(fn)

执行请求并调用`fn(err, res)`。

## 笔记

灵感来自[ api-easy](https://github.com/flatiron/api-easy)。

## 资料

[接口自动化 开源框架学习-supertest](https://blog.csdn.net/lichao330530/article/details/51907075)

[How to Test Your API With Supertest](https://willi.am/blog/2014/07/28/test-your-api-with-supertest/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tdd.shujuwajue.com/ju-ti-shi-jian/javascript-ce-shi-kuang-jia/supertest.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
