关于node.js:在node中测试使用mocha / supertest重定向的请求

Testing requests that redirect with mocha/supertest in node

我似乎无法通过mocha,supertest和should(和coffeescript)在快速项目中通过以下集成测试。

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
should  = require('should')
request = require('supertest')
app     = require('../../app')

describe 'authentication', ->
  describe 'POST /sessions', ->
    describe 'success', (done) ->
      it 'displays a flash', (done) ->
        request(app)
          .post('/sessions')
          .type('form')
          .field('user', 'username')
          .field('password', 'password')
          .end (err, res) ->
            res.text.should.include('logged in')
            done()

相关的应用程序代码

1
2
3
app.post '/sessions', (req, res) ->
  req.flash 'info',"You are now logged in as #{req.body.user}"
  res.redirect '/login'

故障

1
2
1) authentication POST /sessions success displays a flash:
   AssertionError: expected 'Moved Temporarily. Redirecting to //127.0.0.1:3456/login' to include 'logged in'

很显然,应用程序代码没有做任何有用的事情。我只是想让测试通过。

将期望(res.text.should.include('logged in'))放在end函数外部和expect函数内部会产生相同的结果。我还尝试了函数调用的变体,例如删除.type('form')调用,并使用.send(user: 'username', password: 'password')而不是两个.field()调用。

如果有任何意义,则在应用程序本地运行时向应用程序发送curl POST请求会产生相同的输出(Moved Temporarily. Redirecting to //127.0.0.1:3456/login)

我觉得这是一个小错误。可能是我在应用程序代码或测试代码中忘记的东西。

有什么建议吗?

编辑1:同样值得注意的是,在浏览器中单击"提交"按钮时,我得到了预期的结果(即显信息)。

编辑2:进一步调查显示Moved Temporarily. Redirecting to ...响应正文中任何重定向结果的输出。这使我想知道在app.js中导出应用程序的方式是否存在问题。

1
2
3
4
var express = require('express')
var app = express();

module.exports = app;


supertest中有内置的断言:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
should  = require('should')
request = require('supertest')
app     = require('../../app')

describe 'authentication', ->
  describe 'POST /sessions', ->
    describe 'success', ->
      it 'redirects to the right path', (done) ->
        request(app)
          .post('/sessions')
          .send(user: 'username', password: 'password')
          .expect(302)
          .expect('Location', '/home')
          .end(done)

对于碰到此页面的任何人,此问题的答案非常简单。 Moved Temporarily.响应主体是从超级测试返回的内容。有关更多详细信息,请参见此问题。

总而言之,我最终做了这样的事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
should  = require('should')
request = require('supertest')
app     = require('../../app')

describe 'authentication', ->
  describe 'POST /sessions', ->
    describe 'success', ->
      it 'redirects to the right path', (done) ->
        request(app)
          .post('/sessions')
          .send(user: 'username', password: 'password')
          .end (err, res) ->
            res.header['location'].should.include('/home')
            done()

只需检查响应头location是否符合您的期望。测试Flash消息并查看特定的集成测试应使用另一种方法进行。


1
2
3
4
5
6
7
8
9
10
11
12
13
describe 'authentication', ->
  describe 'POST /sessions', ->
    describe 'success', (done) ->
      it 'displays a flash', (done) ->
        request(app)
          .post('/sessions')
          .type('form')
          .field('user', 'username')
          .field('password', 'password')
          .redirects(1)
          .end (err, res) ->
            res.text.should.include('logged in')
            done()

redirects()将遵循重定向,因此您可以进行常规的视图测试。


我试图为重定向的请求编写一些集成测试,并在这里找到了模块作者自己的好例子。

在TJ的示例中,他正在使用链接,所以我也使用了类似的内容。

考虑一种方案,在这种情况下,已登录的用户在注销时将重定向到主页。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
it('should log the user out', function (done) {
  request(app)
    .get('/logout')
    .end(function (err, res) {
      if (err) return done(err);
      // Logging out should have redirected you...
      request(app)
        .get('/')
        .end(function (err, res) {
          if (err) return done(err);
          res.text.should.not.include('Testing Tester');
          res.text.should.include('login');
          done();
        });
    });
});

取决于您有多少重定向,您可能必须嵌套一些回调,但是TJ的示例应该足够了。