我遇到了一些 mocha-cakes 的计时问题针对 restify 运行的测试脚本服务。我正在使用 Restify JSON 客户端发出调用,它使用回调而不是 promise 。我已将 done 函数传递给我的 Given
和 When
,这样我就可以对这些异步调用执行必要的阻止,从而防止不一致的测试套件运行(没有完成,这是一个折腾,以及有多少 Then
和 And
将通过。
我对 coffescript 相当熟练,在 mocha/mocha-cakes 方面只是个新手,所以我的代码肯定有问题。下面是几个失败的测试用例的示例:
require 'mocha-cakes'
should = require 'should'
restify = require 'restify'
Feature "Account API",
"In order to have control over structured Account documents",
"as a consumer of investment account information,",
"I need a RESTful service API.", ->
Scenario "GET /account/:userid", ->
client = restify.createJSONClient
url: "http://localhost:8080",
version: "*"
_e1 = null
_r1 = null
_e2 = null
_r2 = null
_d2 = null
# GET non-existent account
Given "I have not yet created the Account", ->
When "I request the Account", (done) ->
client.get "/account/99", (err, req, res, obj) ->
_e1 = err
_r1 = res
done()
err
Then "it should respond with an error", ->
_e1.should.be.ok
And "the status code should be 404", ->
_r1.should.have.status 404
# GET existent account
Given "I have created the Account", (done) ->
client.post "/account", { userId: 1, accountType: 0, accountCategories: [], beneficiaries: [], accountOwner: { firstName: "Test", lastName: "User" } }, (err) ->
done()
err
When "I request the Account", (done) ->
client.get "/account/1", (err, req, res, obj) ->
_e2 = err
_r2 = res
_d2 = obj
done()
err
Then "it should responond with a document", ->
_d2.should.be.ok
And "it should have the userId 1", ->
_d2.userId.should.eql 1
And "it should have an accountOwner property", ->
_d2.accountOwner.should.be.ok
And "the status code should be 200", ->
_r2.should.have.status 200
当我运行它时,我的输出总是如下:
c:\Development\Clients\Pensco\AngularJS\Pensco\newaccountwizard.api>mocha test/AccountAPITests.coffee -r should -R spec --compilers coffee:coffee-script/register
Feature: Account API
In order to have control over structured Account documents as a consumer of investment account information, I need a RESTful service API. Scenario: GET /account/:userid ◦ - ◊ Given: I have not yet created the Account (pending) ◦ 1) When: I request the Account ◦ √ Then: it should respond with an error ◦ √ And: the status code should be 404 ◦ 2) Given: I have created the Account ◦ 3) When: I request the Account ◦ √ Then: it should responond with a document ◦ √ And: it should have the userId 1 ◦ √ And: it should have an accountOwner property ◦ √ And: the status code should be 200
6 passing (6s) 1 pending 3 failing
1) Feature: Account API
In order to have control over structured Account documents as a consumer of investment account information, I need a RESTful service API. Scenario: GET /account/:userid ◦ When: I request the Account: Error: timeout of 2000ms exceeded at [object Object].<anonymous> (C:\Users\Jon\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:139:19) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
2) Feature: Account API
In order to have control over structured Account documents as a consumer of investment account information, I need a RESTful service API. Scenario: GET /account/:userid ◦ Given: I have created the Account: Error: timeout of 2000ms exceeded at [object Object].<anonymous> (C:\Users\Jon\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:139:19) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
3) Feature: Account API
In order to have control over structured Account documents as a consumer of investment account information, I need a RESTful service API. Scenario: GET /account/:userid ◦ When: I request the Account: Error: timeout of 2000ms exceeded at [object Object].<anonymous> (C:\Users\Jon\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:139:19) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
现在,我知道我通过 client.get/client.post 进行的 REST 调用几乎是瞬间发生的。当我删除完成并在没有它们的情况下运行时,除了重新启动我的 restify 服务服务器后的第一次运行外,通常只有第一次或第二次 Then
/And
失败,其余成功。可能有几毫秒的计时问题,但绝对不是 2000 毫秒。我很好奇为什么当我输入 done()
调用时我的 Givens 和 Whens 突然开始超时。
我很确定我误解了 mocha-cakes 如何将 coffescript Feature->Scenario->Given/When->Then/And/... 转换为 describe/it 调用。我怀疑 done 应用的范围不知何故比 mocha-cakes 脚本结构的性质似乎要大...我只是不确定该范围到底是什么。
最佳答案
我也不熟悉 Mocha 蛋糕。我正在使用 mocha/(lit)coffee 来测试 restify。我发现用 promises 包装我的调用很方便,因为最新的 mocha 是 promise-aware 的。这样我就不必为“完成”而烦恼了。另请注意,您可能需要调用 res.end() 或 res.resume()(参见 this explanation)
对于“GET”:
Promise = require('bluebird') # or whatever, I presume
port = 8776 # ditto
getHttpJson = (addr)->
addr = normalizeUrl(addr)
new Promise ( resolve, reject )->
req = http.get(addr, _completeResponse(resolve) )
.on( 'error', reject )
req.end()
一般情况:
requestHttpJson = (method, addr, data)->
if data?
data = JSON.stringify(data)
urlBits = getUrlBits(addr)
new Promise (resolve, reject)->
req = http.request(
method: method
headers: {
"Content-Type": "application/json" }
hostname: urlBits.hostname
port: urlBits.port
path: urlBits.pathname
, _completeResponse(resolve) )
req.on( 'error', reject )
if data?
req.write( data )
req.end()
postHttpJson = (addr, data)->
requestHttpJson('POST', addr, data)
putHttpJson = (addr, data)->
requestHttpJson('PUT', addr, data)
deleteHttpJson = (addr, data)->
requestHttpJson('DELETE', addr, data)
将地址分解成组件并添加默认值。 (“端口”是一个全局模块。)
getUrlBits = (addr)->
bits = url.parse(addr)
bits.port = bits.port || port
bits.hostname = bits.hostname || 'localhost'
bits.protocol = bits.protocol || 'http'
return bits
normalizeUrl = (addr)->
url.format(getUrlBits(addr))
解析请求体和解析的实用程序。
_completeResponse = (resolve)->
(res)->
body = []
res.on 'data', (data)->
body.push data
res.on 'end', ->
body = body.join ''
content = if body == '' then null else JSON.parse(body)
resolve([res,content])
关于使用 Mocha-Cakes 和 Coffescript 测试 Restify 服务,在异步中使用 done() 会导致超时问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23299228/