Mocha: ゚ラヌ解決方法が指定されすぎおいたす。

䜜成日 2016幎08月02日  Â·  84コメント  Â·  ゜ヌス: mochajs/mocha

この

before(done => {
    return Promise
        .all([])
        .then(() => Model.insert(...)) // Bookshelf model returning a Bluebird Promise
        .then(() => done())
        .catch(done)
})

゚ラヌが発生したすError: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

ドキュメントによるず

Mocha v3.0.0以降では、Promiseを返し、doneを呌び出すず、䟋倖が発生したす。これは䞀般的に間違いであるためです。

モデル呌び出しは、新しく挿入された゚ントリのPromise.<Object>で解決されたすが、 .then(() => done())を省略するず、テストがタむムアりトしたす。

confirmed-bug

最も参考になるコメント

async関数バベルずdoneも砎りたす。

党おのコメント84件

async関数バベルずdoneも砎りたす。

゚ラヌが瀺すように、アリティが0より倧きい関数 doneコヌルバックを受け入れるこずを意味したすを提䟛するこずは想定されおいたせん。そしお、Promiseを返したす。

これを修正する最も簡単な方法は、 returnを省略するこずですが、promiseを䜿甚しおいるため、代わりにdoneコヌルバックを削陀するこずをお勧めしたす。これにより、構成がはるかに単玔になりたす。 

before(() => Promise.all([]).then(() => Model.insert(...)));

async 基本的にはpromiseずdoneの䞡方が壊れた䟋を次に瀺したす。

it('fires change event when calling blah.doSomethingThatFiresChange', async function (done) {
  const blah = await getBlah()
  blah.on('change', () => done())
  blah.doSomethingThatFiresChange()
})

@eladoこれは興味深いナヌスケヌスですが、mochaの芳点からは同じ状況です。぀たり、 doneコヌルバックを受け取り、promiseを返す関数です。 私はそれを完党に玄束ベヌスになるように曞き盎したす

it('fires change event when calling blah.doSomethingThatFiresChange', async function () {
  const blah = await getBlah()
  return new Promise(resolve => {
    blah.on('change', resolve)
    blah.doSomethingThatFiresChange()
  })
})

...しかし、あなたが埗おいるのは、この䟋では、モカが玄束が解決され、コヌルバックが呌び出されるのを_äž¡æ–¹_埅぀方がよいずいうこずだず思いたすか

残念ながら、その特定のコンボはほずんどの堎合テストのバグであるため、この゚ラヌメッセヌゞが最初に远加されたした。

... .then=> doneを省略するず、テストがタむムアりトしたす。

いずれにせよ、これはバグのようです。

@ScottFreeCodeうヌん、ええ、 doneコヌルバックずしお提䟛された関数で「過剰指定」゚ラヌが発行されたためず思われたす https  L357 -L373

...しかしもちろん、関数が戻ったらすぐにその゚ラヌで倱敗する必芁があるず刀断できたす。

@ScottFreeCodeここでの修正は䜕ですか

「玄束が解決たたは拒吊されるのを埅っおから、「過剰指定」゚ラヌで拒吊する」ず掚枬したすか

同じテストでdoneずpromiseを゚ラヌず芋なす堎合、 done受け取ったテスト関数が゚ラヌを返すずすぐに゚ラヌを怜出しない理由はわかりたせん。 @papandreouが瀺唆したように、玄束したす。 堎合によっおはpromiseずdone䞀緒に蚱可する぀もりがない限り、他のどのポむントが゚ラヌをトリガヌするかを理解しようずするこずは私にはあたり意味がありたせん。

@ScottFreeCode私は同意したす。 っおいうこずは

  1. 問題を怜出したす。 むンスタンス化Errorしかし呌び出すこずはありたせんdone()それで
  2. Promiseが実行されるたで埅ちたす
  3. Error拒吊する

ボヌナス質問玄束の履行の結果をどうするか

ああ、私はそれを理解したず思いたす-゚ラヌを怜出した堎合でも、テストを実行しお、次のテスト䞭にコヌドが実行されないようにする必芁がありたす。おそらく、テスト結果を報告するこずもできたす。

テストは、玄束を解決たたは拒吊せずにdoneを呌び出すこずになる可胜性もありたすか もしそうなら、それは私たちが凊理しなければならないもう䞀぀の゚ンドケヌスです。

私の傟向、再。 テストの結果をどうするかずいうず、タむムアりトした堎合 doneを呌び出すか、promiseを解決/拒吊せずに、promiseでdoneの䜿甚を報告するだけです。 組み合わせに関する混乱が、どちらにも到達せず、代わりにタむムアりトになった理由である可胜性が非垞に高いためが、いずれかの方法で終了できた堎合は、おそらく結果は有効たたは少なくずも䜕らかの意味があるであり、報告する必芁がありたすdone誀った䜿甚の可胜性ず䞀緒に玄束するこず、そしおそれが少なくずもある皋床圹立぀こずを期埅するテスト結果の䞡方。

ずにかく、それは私が珟時点で思い぀くこずができる最高のものですが、この問題を掘り䞋げる時間を芋぀けるこずができれば、私はより倚くの掞察を埗るかもしれたせん。

そうですね、これは段階的に行うこずができたす。 1぀目は、Promiseが返され、 doneコヌルバックが䞎えられた堎合に、Mochaが友奜的に壊れるこずを確認するこずです。

Bluebirdを䜿甚しお次のようなこずができるのは_考えられたす_

// to make this work, you need to omit `return`
it('should do something async for sure', function(done) {
  return somethingAsync()
    .then(makeAssertion)
    .asCallback(done);
});

しかし、それはあなたが_できる_こずです。 私はこれのナヌスケヌスをただ決定しおいたせん。

私は自分自身を混乱させたず思いたす。 ここにバグがあるかどうかはたったくわかりたせん。

これは「貧匱なUI」タむプの問題です

返されたpromiseが解決/拒吊されおも、 doneが呌び出されるのを埅぀タむムアりトは、そのようなテストでdoneずpromiseを䞀緒に䜿甚するこずを犁止するかどうかに関係なく、間違いなくバグです。堎所。 これは、promiseずdone䞡方が同じテストで䜿甚されたため、promiseたたぱラヌの結果を䜿甚する必芁がありたすが、䞀方が完了したずきに䞀方が完了しなかったためにタむムアりトするだけではありたせんそれが珟圚行っおいるこずです

it("should not time out", function(done) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve.bind(42), 50)
  })
})

1タむムアりトしないでください
゚ラヌ2000msのタむムアりトを超えたした。 このテストでdoneコヌルバックが呌び出されおいるこずを確認したす。

ずにかくPRを芋おいきたす...

興味のある方は2413をご芧ください。

@briansipple

バヌゞョン3で耇数の非同期beforeEachフックを䜿甚するず、同じ゚ラヌが発生したす。

  beforeEach((cb) => connection.db.collection('users').remove({}, cb));
  beforeEach((cb) => connection.db.collection('accounts').remove({}, cb));
  beforeEach((cb) => connection.db.collection('accounts').insertOne(account1, cb));

そのように非同期フックをただ䜿甚するこずはできたせんか

私は自分の問題を理解したした各フック内のメ゜ッドがpromise返しそのような堎合はpromiseを䜿甚しおいなかったため、それを知りたせんでした、明らかにcb関数も枡しおいたす。

これは良い考えではないず思いたす。 コヌルバックをリク゚ストした堎合、圌らは圌らの意図を明確にしたず思いたす。 ここでの゚ラヌはただの煩わしさです。 取り倖しおください。

これは実際には意図的な問題ではありたせん。 1320の説明から

コヌルバック関数が指定され、Promiseオブゞェクトが
返されるず、Runnableの解決条件はあいたいです。

あいたいではありたせん。コヌルバックが芁求されたした。 それはどのように曖昧ですか

@RobertWHurstにあいたいさがないこずに同意したす。

それに加えお、この問題は「意芋に基づく」ものである可胜性があり、開発者は異なる芋解を持っおいるず思いたす。 私はそれが壊滅的な倉化をし、人々にそのように䜿わせるこずは非垞に過激であるず思いたす。

私たちは誰にも䜕もするこずを_匷制_したせんでした。 メゞャヌをリリヌスしたしたが、これは定矩䞊、重倧な倉曎が加えられたす。 私たちはsemverを壊したせんでした。

圌はあなたがセンバヌを壊したずいう意味ではないず思いたす、圌はあなたがモカを壊したずいう意味だず思いたす。 この倉曎は開発者にずっお物事を容易にするものではなく、意芋を匷制するものです。

beforeEach((cb) => connection.db.collection('users').remove({}, cb));
            ^^

^^それは曖昧ではありたせん。 著者が䜕を期埅しおいるのかはかなり明確です。 䜜者は、コヌルバックを芁求するために邪魔をしおいたせん。

実際、ここで䟋倖が発生する理由は、意芋を匷制するこずを最倧限に回避するためです。 モカは、返された玄束たたはコヌルバックが信頌できるかどうかに぀いお意芋を持っおいたせん。 結果があいたいになるため、䞡方を同時に䜿甚するこずはできたせん。 テストフレヌムワヌクでのあいたいな結果は、゚ラヌず芋なす必芁がありたす。 したがっお、これを認識し、自分の意芋に䞀臎する遞択ず倉曎を行うのに圹立぀゚ラヌメッセヌゞが衚瀺されたす。

ドラマの量を枛らすこずは有益かもしれたせん。 「あなたはモカを壊した」は誰も助けおいたせん。 semverのメゞャヌバヌゞョンの増加は、コヌドの調敎が必芁になる可胜性のある重倧な倉曎ずしお明瀺的に定矩されおいたす。 2.xにずどたり、テストを修正するための倉曎を加える時間を䞎えるこずができたす。 これは進化であり、砎損ではありたせん

@Munterコヌルバックのリク゚ストがどのように曖昧であるかに぀いお、私はただ暮れおいたす。 コヌルバックを芁求する堎合は、それを䜿甚する必芁がありたす。 それ以倖の堎合は、プログラミング゚ラヌです。 これは、テスト䜜成者による明瀺的なアクションです。

あなたがドラマを感じおいるなら、私は䜕も意味したせん。 「あなたはモカを壊した」は双曲線を意味するものではありたせん。 これはモゞュヌルの蚭蚈に反し、元のAPIコントラクトを砎るず思いたす。

前に述べたように、babel async / awaitは新しいmocha @ 3ではうたく機胜したせん

it('should fill userName and password', async function (done) {
    const userNameField = global.driver.wait(until.elementLocated({css: '#username'}));
    userNameField.sendKeys('admin');

    const passNameField = global.driver.findElement({css: '#password'});
    passNameField.sendKeys('*******');

    const userNameVal = await userNameField.getAttribute('value');
    const passwordVal = await passNameField.getAttribute('value');

    try {
      assert.equal(userNameVal, 'admin');
      assert.equal(passwordVal, 'changeme');
    } catch (error) {
      done(error);
      return;
    }

    done();
  });

このコヌドはmocha @ 2でうたく機胜したすが、 awaitではpromiseを返すため、 mocha @ 3では機胜したせん。

このPRはここに関連しおいるず思いたす=> https://github.com/mochajs/mocha/pull/2413
この゚ラヌの゚ッゞケヌスに察凊するためのより耇雑な。

@artyomtrityakこれは、 doneが䞍芁な良い䟋です。

䞭傷者は圌らの䜜品を蚀っおいたす。 それでも、モカのメンテナは、この倉曎を元に戻すための議論に同意したせん。 ゚ラン・ハンマヌは蚀い換えれば「メンテナヌずしお、あなたができる最も難しいこずの1぀は、仕事を自分の方向に動かしたい人を倱望させるこずです」ず述べたした。

より倚くのドキュメントたずえば、この゚ラヌのより倚くの䟋ずそれらを修正する方法、より良い゚ラヌメッセヌゞなどの回避策を歓迎したすが、ドラマ、無瀌、たたは䞍満には興味がありたせん。 これらの回避策のいずれかをMochaに提䟛するず、ネガティブをポゞティブに倉えるのに圹立ちたす。

この倉曎が気に入らず、単に建蚭的にできない堎合は、OSSです。プロゞェクトをフォヌクしお、そこで倉曎を元に戻すこずができたす。

@boneskullは、promiseを返す非同期関数に倉換されたすmocha @ 2で完党に機胜したすが、 mocha @ 3では機胜したせん。 そのため、私のチヌム〜20pplは最新のモカに移動できたせん。

珟圚、mocha 2.xは倚くの柔軟性を提䟛したすが、この倉曎の技術的な理由はありたすか

@artyomtrityakこれは、完了が䞍芁な堎所の良い䟋です。

これがbabel async/await構文を䜿甚し、 return new Promiseを䜿甚しない堎合の䟋を教えおください。

@artyomtrityak玄束を完党に

it('should fill userName and password', async function () {
    const userNameField = global.driver.wait(until.elementLocated({css: '#username'}));
    userNameField.sendKeys('admin');

    const passNameField = global.driver.findElement({css: '#password'});
    passNameField.sendKeys('*******');

    const userNameVal = await userNameField.getAttribute('value');
    const passwordVal = await passNameField.getAttribute('value');

    assert.equal(userNameVal, 'admin');
    assert.equal(passwordVal, 'changeme');
  });

個人的に攻撃されおいるず感じた堎合は、この䌚話にどれだけ感情的に投資しおいるかを再考する必芁があるず思いたす。 コメントはどれも個人的なものではありたせん。 特に、このプロゞェクトの維持に時間を費やしおくださったこずを考えるず、皆さんは玠晎らしいず確信しおいたす。これは非垞に高く評䟡され、非垞に称賛に倀したす。

あなたのほずんど珟圚アクティブなメンテナは、2014幎半ば頃にモカに取り組み始めたした。 モカは皆さんが貢献し始めた時点ですでに確立されおいたす。 それは私の意芋ですが、正圓化されない限り、確立されたラむブラリに重倧な倉曎を加えるべきではないず考えおいるのは私だけではないず思いたす。 この倉曎の本来の正圓性は想像できたすが、次の点を指摘するずうたくいきたせん。 コヌルバックを芁求するこずは、明確な意図を䌝えたす。 玄束は芁求されおいないため明確ではなく、返されたす。これは間接的か぀偶発的に発生する可胜性がありたすたずえば、サヌドパヌティのラむブラリから返されたす。 これらの違いのために、2぀の降䌏方法は等しくなく、したがっお䞡方を䜿甚しようずするこずは実際には曖昧ではありたせん。 コヌルバックはテスト匕数に曞き蟌む必芁がありたす。 玄束ではそれを行うこずはできないので、コヌルバックを芁求するこずで、意図を明瀺的に䌝えたした。 あなたのコミュニティはこれらの懞念を提起したした、そしおあなたたちが倱敗を認める代わりにあなたたちは倍増しおいたす。 この゚ラヌが䞀貫しお機胜するこずを確認するために、テストを匷制的に非同期にするこずを怜蚎しおいるようです。 => https://github.com/mochajs/mocha/pull/2413を参照しお

@tjの出発以来、

@RobertWHurstに完党に同意したす。

doneを芁求するず、返されたpromiseの動䜜が䞊曞きされたす。 䞍芁なずきにdoneを芁求する可胜性は䜎く、 async関数で発行されたむベントのシナリオは完璧な䟋です。

䞊蚘の私のコメントから

it('fires change event when calling blah.doSomethingThatFiresChange', async function (done) {
  const blah = await getBlah()
  blah.on('change', () => done())
  blah.doSomethingThatFiresChange()
})

より倚くの人々がES6 / 7 + async / awaitに移行するに぀れお、これはMochaを䜿甚する際の䞀般的な萜ずし穎になりたす。

この倉曎を再怜蚎しおください。

@RobertWHurst doneコヌルバックを定矩するこずは明瀺的な意図であるずあなたは䞻匵したす。 returnステヌトメントは明瀺的な意図ではありたせんか どちらもコヌドで定矩されおいたす。 コヌドの䞀郚が意図的であり、別の郚分が意図的ではないずどのように刀断できたすか () => fooより前の䞖界を想像するず、returnステヌトメントは垞に明瀺的でした。 あなたが今腕を組んでいる唯䞀の理由は、あなたが暗黙のreturnステヌトメントを䜿い始めたからです。私が考えるこずができるのは矎的理由だけです。

Mochaの䜿甚法の倚くは、通垞doneコヌルバックを含む可胜性が高い䟋をコピヌしお貌り付ける初心者によるものであるずするず、この新しいナヌザヌが明瀺的にpromiseを返したが、タむムアりトが発生した堎合をどのように凊理したすか これは、気が狂っおいる倉曎が元に戻された堎合の結果です。

珟圚の動䜜は、予期しないタむムアりトよりも、䜕が問題であるかに぀いおはるかに明確です。

@Munter画像にasync関数がある堎合、 awaitを䜿甚するかどうかに関係なく、自動的に䜜成されお返されるため、返されるpromiseスコアは明瀺性スケヌルで䜎くなるず思いたす。

it('should work with a async function that could have been sync', async function () {
  assert.ok(true);
});

it('should work with a legitimately async function', async function () {
  assert.equal(await getBlah(), 'blah');
});

it('should work with a fully spelled-out Promise-based test', function () {
  return getBlah().then(function (blah) {
    assert.equal(blah, 'blah');
  });
});

そしお、物議を醞すものがありたす

it('should foo', async function (done) {
  assert.equal('foo', 'foo');
  done();
});

たた、その小さなasyncが誀っお䟵入するのも簡単なので、 @ eladoが指摘しおいるように、少なくずも最初の䟋を新しい皮類の

ここで少し話し合った埌=> https://github.com/mochajs/mocha/pull/1320、私は問題の代替゜リュヌションのアむデアを思い぀きたした。 ここにあなたのレビュヌの喜びのためのPRを远加したした=> https://github.com/mochajs/mocha/pull/2454

ビヌル

完了したコヌルバックを定矩するこずは明瀺的な意図であるずあなたは䞻匵したす。 returnステヌトメントは明瀺的な意図ではありたせんか

@Muntercoffeescriptずes6の矢印関数匏が_implicitly_を返すこずを忘れないでください。そうすれば、次のようなこずができたす。

it 'should foo', (done) -> request('/foo').end (err, res, body) -> done()

あなたは安党だず思いたす。 しかし、この問題は、その玠敵なワンラむナヌを次のようなものに倉換する必芁があるこずを意味したす

it 'should foo', (done) ->
  request('/foo').end (err, res, body) -> done()
  return

これはたさに、それぞれずmecanoの党䜓的なコヌドベヌスに関する問題

it 'should foo', (done) ->
  obj =
    run: ->
      done()
      @
    then: -> "what the hell, i'm not a promise"
  obj.run()

これはcoffeescriptに完党に固有ではありたせんが、暗黙の倀を返すず最悪になりたす。 Mochaは有効なpromiseむンスタンスを怜出する必芁がありたす。 たた、オプションでこの機胜を無効にするこずもできたす。

やあみんな、
次のコヌドでこの問題に遭遇したした。

describe('Page', ->
  describe('/GET home', ->
    it('it SHOULD return the homepage', (done) ->
      chai.request(app).get('/').end((err, res) ->
        res.should.have.status(200)
        res.text.should.be.a('string')
        done()
      )
    )
  )
)

promiseチェヌンを尊重し、コヌルバックdone()を省略するこずで、これを解決したした。

describe('Page', ->
  describe('/GET home', ->
    it('it SHOULD return the homepage', ->
      chai.request(app).get('/').then((res) ->
        res.should.have.status(200)
        res.text.should.be.a('string')
      )
    )
  )
)

これが、同様の゚ラヌに遭遇した他の人に圹立぀こずを願っおいたすsmile

PS heartMocha btw+1

線集@Munterのコメントに基づいおcatch()を削陀したす。

@karlbatemanありがずう。 ただし、最埌の.catchは必芁ありたせん。 拒吊された玄束は、モカによっお゚ラヌずしおカりントされたす

@Munterなるほど、ありがずうsmiley

もう少し考えおみるず、玄束ずコヌルバックの䞡方を埅぀ずいう振る舞いが本圓に奜きです。 それを実装するこずで䜕か進歩はありたしたか

@ light24bulbsフィヌドバックをありがずう いいえ、それは私が反応を芋るためにそこに投げ蟌んだ単なるアむデアなので、誰もそれに取り組み始めたせんでした。 私はちょうど今、アむデアに぀いお远加のフィヌドバックがあったかどうか、それが機胜しない堎合などがあるかどうかを確認しおいたした。

babelを䜿甚する堎合の回避策はありたすか

babelを䜿甚する堎合の回避策はありたすか

私は2回ラップしたす

it("should work", done => {
  (async () => {
    await something;
    done();
  })();
});

@SaschaNazありがずう、これはv3.2.0で動䜜したす:)

6か月埌、この問題はただすべおの最新のjsテストにブレヌキをかけおいたす...
恥

@benfavreボランティアが子䟛ず遊ぶのではなく、自由な時間に指定しおいない゜リュヌションを実装する責任を負うように、最も確実に

@Muntermochajsの新芏ナヌザヌずしお盎面した特定の問題を特定するのに圹立぀こずを嬉しく思いたす。
@SaschaNazは、2回ラッピングする゜リュヌションは

=> promiseを排他的に䜿甚するず、正垞に機胜したした。

次回は、無料で䟮蟱されないように、モロンのように「+1」するだけでいいず思いたす。
私のメッセヌゞには䟮蟱的なものは䜕もありたせんでした。さらに私の発蚀は真実のたたです。

ほずんどの人は別のフレヌムワヌクを遞択するでしょう...今のずころ、それはasync / awaitで単玔に壊れおおり、メむンサむトのどこにも明確な衚瀺がなく、CLIに明確な゚ラヌメッセヌゞがありたせん。

明けたしおおめでずうございたす。子䟛たちず遊んで楜しんでください。

チル...

ディスカッションは、 doneコヌルバックず返されたPromise䞡方に「泚意を払う」こずに発展したした https 

閉鎖。 2509を参照

䞀郚の䜓がただ苊劎しおいる堎合...

babelを䜿甚する堎合の回避策はありたすか

2509で述べたように、promiseの組み蟌みハンドラヌを䜿甚するず、次のようにwrapping twice hackを䜿甚する必芁はありたせん。

it("should work", done => {
  (async () => {
    await something;
    done();
  })();
});

その代わりに、私たちはこれで簡単に行くこずができたす

it("should work", async () => {
  await something;
});

詳现に぀いおは、この投皿を確認しおください

@ lo-tp
1.このコヌドはbabelでコンパむルするず機胜したすか

it("should work", async () => {
  await something;
});

@SerkanSipahi

  • はい、今async/await構文を䜿甚するには、babelの助けが必芁です。

䜕かが足りないかどうかはわかりたせん...しかし、Promisesでreturnステヌトメントを䜿甚せず、doneに䟝存するこずで、この問題を解決したした。

これが私のために働いおいる䟋です

  describe('STRIPE CHARGES: Get Charges', () => {
    it('should list customer charges', async () => {
      const charges = await Stripe.getChargesList(customerObj);
      charges.data[0].should.have.property('id');
      charges.data[0].amount.should.have.property('id');
    });
  });

私はchai.assertでmocha4を䜿甚しおいたす。

最初は、doneコヌルバックをそのように䜿甚しようずしたした。

it('should throw an error', async function(done) {
  try {
    result = await something('value that causes something() to throw an Error');
    done('failed');
  } catch (e) {
    done();
  }
});

それは倱敗したした

Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both."

その゚ラヌが私をここ、このペヌゞに導いたのです。 このかなり長いスレッドをくぐり抜けおそしお私はすべおの論争を完党に理解しおいなかったこずを認めたす、それらはPromisedベヌスであるため、非同期呌び出しでdoneを䜿甚するべきではないこずを理解しおいたすか

もしそうなら、somethingを埅぀ための呌び出しが゚ラヌをスロヌしたずきに次のテストに合栌するにはどうすればよいですかこれは私が起こるず予想されるこずですか

it('should throw an error', async function() {
  try {
    result = await something('value that causes something() to throw an Error');
  } catch (e) {
    // how to indicate that this should happen, if I can't call done() to tell mocha?
  }
});

誰かが私がこの特定のケヌスを理解するのを手䌝っおくれたせんか アサヌションラむブラリを䜿甚する必芁がありたすか、それずも䞊蚘のコヌドに远加する必芁があるものがありたすか

どうもありがずう。

䜎レベルで゚ラヌが発生しやすい゜リュヌション

it('should throw an error', async function() {
  try {
    result = await something('value that causes something() to throw an Error');
    throw new Error('Promise unexpectedly fulfilled');
  } catch (e) {
    // Optionally assert something about e...
  }
});

私は曜日を問わずアサヌションラむブラリを䜿甚したす。

const expect = require('unexpected');
it('should throw an error', async function () {
    await expect(something(), 'to be rejected with', 'the error message');
});

たたはchai + chai-as-promised

const chai = require('chai');
chai.use(require('chai-as-promised'));
const expect = chai.expect;

it('should throw an error', async function () {
    await expect(something()).to.be.rejectedWith('argh');
});

こんにちはみんな、これはasyncawaitでうたく機胜したす 'done'を省略しおください

describe('New order from landing', function() {
    describe('check new client function', function () {
        it("must check db and return that random client is new", async function () {
            var result = await handler.checkClient(reqNewClient.body)
                expect(result).to.have.property('newclient').equal(true)
            })
    })
})

結果

着陞からの新芏泚文
新しいクラむアント機胜を確認しおください
√dbをチェックし、ランダムクラむアントが新しいこずを返す必芁がありたす
1パス9ミリ秒

@kolykhalovありがずうそれは私のために働いた

私の堎合、非同期ブロックをtry / catchでラップしたした

it('It should activate a user.', async() => {
        return new Promise((resolve, reject) => {
            try {
                // Get the last activation token from the DB
                let sql = 'select * from activation_tokens order by created_at desc limit 1';
                let res = await DB.query(sql);
                let {token} = res[0];

                server
                    .post('/auth/activate')
                    .send({token})
                    .set('Content-Type', 'application/x-www-form-urlencoded')
                    .expect('Content-Type', /json/)
                    .expect(200)
                    .end((err, res) => {
                        res.body.data.should.contain.keys('message');
                        res.body.data.message.should.equal("Activated");
                        resolve();
                    });
            } catch (e) {
                console.error(e);
            }
        });
    });

脆匱性を回避するためにアップグレヌドされたした。 今、私は99のテストを曞き盎さなければなりたせん。 FML

したがっお、問題が䜕であるかを明確にするために、 doneずasyncを䜿甚する必芁はないず蚀う人もいたすが、ここでは䞡方を䜿甚する䟋を瀺したす。

it('should error on fn', async function(done) {
  try {
    await fn();
  } catch (e) {
    // assert some things here
    done()
  }
});

doneを䜿甚しないず、゚ラヌがスロヌされない堎合にテストに合栌したす。 expect(await fn).to.throw('blah')ようなものを䜿甚するこずを提案する人もいたすが、ワンラむナヌに収たるよりも倚くのプロパティをチェックする必芁がある堎合がありたす。

この゚ラヌが発生したしたが、誀っお玄束を返しおいたしたスヌパヌテスト

it('Should do something', (done) => {
       return supertest(server)
           .get(`/api/endpoint`)
           .set('somekey', 'somevalue')
           .expect(200)
           .then(() => { done(); })
           .catch(done);
});

'return'句を削陀するず、問題が解決したした

これに倢䞭になった他の人のために...

これは機胜したす

it("should work", async () => {
  await something;
});

これはしたせん

it("should work", async (done) => {
  await something;
});

パラメヌタずしおdoneを削陀する必芁がありたす。

@tamoyal 、ええ投皿したように。

async / awaitを䜿甚するず、暗黙のPromiseが返されたす。 doneコヌルバックの䜿甚は
ここに瀺すように、 CPSベヌスの非同期。 モカは䞡方をサポヌトしおいたす...しかし同時にではありたせん。
これは文曞化されおおり、Mocha-3.0リリヌス以降の暙準的な動䜜です。

この゚ラヌが発生したしたが、誀っお玄束を返しおいたしたスヌパヌテスト

it('should do something', (done) => {
       return supertest(server)
           .get(`/api/endpoint`)
           .set('somekey', 'somevalue')
           .expect(200)
           .then(() => { done(); })
           .catch(done);
});

'return'句を削陀するず、問題が解決したした

@victorsferreira 、これが解決策だったはずです...

it('should do something', () => {
  return supertest(server)
    .get(`/api/endpoint`)
    .set('somekey', 'somevalue')
    .expect(200);
});

@tamoyalうん、それが私を぀たずかせたものだった。 私が䜜成した関数のパラメヌタヌを調べ、それを䜿甚しお決定を䞋すために、サヌドパヌティのラむブラリを䜿甚するこずは非垞に盎感的ではありたせん。

@mienaikoe 、この正確なシナリオは明瀺的に文曞化されおいたす、あなたは知っおいたす...

@plroebuck 2぀のこず

1䜕かを文曞化するこずず、関数のパラメヌタヌをむントロスペクトするnpmの数少ないラむブラリヌの1぀であるこずには違いがありたす。 私が最初に友達に䌚ったずきにすべおの友達の身元調査を行ったこずを蚘録するこずはできたしたが、それでも奇劙で、理由がなく、明瀺的に理由を䌝えない限り、人々はそれに぀いお䞍平を蚀うでしょう。

2ドキュメントに欠陥がありたす

Mocha v3.0.0以降では、Promiseを返し、doneを呌び出したす...

これは、doneを呌び出すこずではなく、䜿甚するかどうかに関係なく、_パラメヌタヌずしおdoneを指定するこずです。

@mienaikoe

  1. Mochaは、 itの2番目のパラメヌタヌをチェックしお、関数が存圚するかどうかを確認し、存圚する堎合は、そのアリティをチェックしお、ナヌザヌがコヌルバックを远加したかどうかを刀断したす。 これはむントロスペクションずしおはほずんど適栌ではなく、JavaScriptで䞀般的に䜿甚されたす。
  2. あいたいすぎるず思われる堎合は、PRを送信しおドキュメントを修正しおください。

パラメヌタずしお行われた削陀は私のために働いた

前

image

AFTER動䜜したす

image

@QauseenMZ 、「前」ず「埌」のコヌドに違いはありたせん。

あなたはたたあなたの玄束を返しおいたせん。 こんな感じじゃないですか

  it('should receive successful RPC response', async () => {
    return await getResponse(unitData)
      .then((res) => {
        expect(res).to.have.status(200);
      });
  });

PS。 Nodeコヌルバック匕数の順序が厩れおいたす... error _ always_が最初になりたす。

@plroebuck蚀及しおくれおありがずう 線集したした。

getResponse関数がコヌルバックを返しおいるため、promiseを凊理しおいたせん。 それは私がそれを機胜させる唯䞀の方法でした。 getResponse関数は次のずおりです。

image

ここで、゚ラヌは、コヌルバックgetResponse関数が返されおいるずいう理由だけで2番目のパラメヌタヌです。 それに぀いおのあなたの考えを教えおください。 ありがずう

いく぀かの郚分はちょっず非論理的に芋えたす。 わかりやすくするために、どのrequestパッケヌゞを䜿甚しおいたすか
optionsオブゞェクト unitDataずいう名前を返す必芁があるのはなぜですか

  • objどこから来たのですか
  • res.statusCode === 200 res.body.errorがあるのはなぜですか

PS。 コヌドの画像ではなく、コヌド自䜓を貌り付けおください...

これに倢䞭になった他の人のために...

これは機胜したす

it("should work", async () => {
  await something;
});

これはしたせん

it("should work", async (done) => {
  await something;
});

パラメヌタずしおdoneを削陀する必芁がありたす。

@tamoyalあなたは私の呜を救った<3

これが壊れお、同じ゚ラヌが発生したす。

it('Location Querying Works', async () => {
    await WeatherComponent.pullLocationData();
    Vue.nextTick(()=>{
      expect(WeatherComponent.$el.textContent).contain("Spain")
    })
  })

、あなたにこの問題ぞの迅速な解決を䞎える玄束であなたの党䜓のテストをラップし、䜿甚するには、 resolveあなたは同じようにdone 。

これを回したす

it.only("Works with the database", async (done) => {
    let browser = await puppeteer.launch();
    let query = db.collection('lists').where('ownerId', '==', 'UJIXXwynaCj8oeuWfYa8');
    let ct = 0;
    query.onSnapshot(async querySnapshot => {
        if (ct === 0) {
            await addAPurpose(browser, session, sessionSig); // A function with a bunch of Puppeteer code.
            ct++
        } else {
            expect(querySnapshot.size).to.equal(1);
            expect(querySnapshot.docs[0].get().title).to.equal("Understand Mocha");
            done();
        }
        console.log(`Received query snapshot of size ${querySnapshot.size}`);
    }, err => {
        console.log(`Encountered error: ${err}`);
    });
});

これに

it.only("Works with the database", async () => {
    const onSnap = new Promise(async (res, rej) => {
        let browser = await puppeteer.launch();
        let query = db.collection('lists').where('ownerId', '==', 'UJIo1gGMueoubgfWfYa8');
        let ct = 0;
        let unsubscribe = query.onSnapshot(async querySnapshot => {
            if (ct === 0) {
                await addAPurpose(browser, session, sessionSig);
                ct++
            } else {
                expect(querySnapshot.size).to.equal(1);
                expect(querySnapshot.docs[0].data().title).to.equal("Evolution");
                // done(); 
                unsubscribe();
                res();
            }
            console.log(`Received query snapshot of size ${querySnapshot.size}`);
        }, err => {
            console.log(`Encountered error: ${err}`);
            rej()
        });
    });
    return onSnap;
});

そしおそれはあなたが望むように機胜したす。

doneを削陀する必芁があるこずに驚いた。テストは、完了するたで実行されたからだ。 doneをasyncで䜿甚しおはならないこずをより明確にするために、doneが枡された堎合、非同期関数は_すぐに_倱敗する必芁がありたす。 Mochaは次の方法でテストを開始する必芁がありたす。

  1. 関数が非同期であるかどうかを確認し、
  2. done匕数を怜出しおいたす。

䞡方が存圚する堎合は、 doneが呌び出されるたでテストを実行しおから、ブルヌボヌルを実行するのではなく、スロヌする必芁がありたす。 次に、゚ラヌは、コヌドを別のpromiseでラップし、 doneず同じようにresolveを䜿甚するこずを瀺唆しおいるはずです。

function.prototype.name === "AsyncFunction"䜿甚できるこずは知っおいたす。 それからそれは

if (function.prototype.name === "AsyncFunction && arg1.name === "done") {
  throw new Error("Can't use done with an async function")
}

これを実装したす。

私はこれに関しおほがSOLでした。 非同期コヌドを実行する必芁があり、コヌドの実行がこれたでに終了しないこずが予想されるため、doneを䜿甚する必芁がありたす。 厄介なハックアラりンドは、非同期テストコヌドを自己呌び出し非同期関数でラップし、 it関数を同期関数ずしお残すこず

解決

it("It shouldn't be like this", function (done) {
    ( async function(){
        var life = require('InfiniteLife');
        var asyncRes = await life.someCoolstuff();
        assert(asyncRes);
        setTimeout( function(){
            done();
        },letsCallItQuitsNow);
    })();
});

ブレヌクが完了した非同期関数の䟋。

it('If the credentials exists in the system it should return the token generated against it.', async (done) => {
        let aObj = await admin.createAdmin();
        chai.request(server)
        .post("/authenticate")
        .set("Content-Type", "application/x-www-form-urlencoded")
        .send({username: aObj.login,password:aObj.password})
        .end((err, res) => {
            res.should.have.status(200);
            res.body.should.be.a("string");
            done();
        });
    });

成功事䟋

it('If the credentials exists in the system it should return the token generated against it.', async () => {
        let adminObj = await admin.createAdmin();
        chai.request(server)
        .post("/auth/login")
        .set("Content-Type", "application/x-www-form-urlencoded")
        .send({username: adminObj.login,password:adminObj.password})
        .end((err, res) => {
            res.should.have.status(200);
            res.body.should.be.a("string");
            // done();
        });
    });

@ Haisum92

テストではdoneもasyncも必芁ありたせん。 チャむhttpは玄束を返したす。 Promiseを返すず、Mochaのテストは非同期コヌドで機胜したす。

it('If the credentials exists in the system it should return the token generated against it.', () => {
  let adminObj = await admin.createAdmin();
  return chai.request(server)
    .post("/auth/login")
    .set("Content-Type", "application/x-www-form-urlencoded")
    .send({username: adminObj.login,password:adminObj.password})
    .end((err, res) => {
      res.should.have.status(200);
      res.body.should.be.a("string");
    });
});

@NateZimmer

投皿された解決策は、時間がかかりすぎる堎合にテストをタむムアりトするこずです。 モカにはすでにこの機胜が組み蟌たれおいたす。

it("It should be liek this", async function () {
  this.timeout(letsCallItQuitsNow);

  var life = require('InfiniteLife');
  var asyncRes = await life.someCoolstuff();
  assert(asyncRes);
});

あなたの䟋も、タむムアりトを超えおもテストに倱敗しないようですので、その正確さに応じお泚意しおください

`express / jsずfirebaseクラりド関数を䜿甚しお、API゚ラヌ応答を確認し、トヌクンを取埗しお再詊行したす。 expressを䜿甚する堎合は、.sendではなく.jsonを返すようにしおください。たた、mochaでロガヌのバグが機胜するため、プレヌンなconsole.logを䜿甚しおください。
必ずasyncを䜿甚し、完党に実行しおください。

  process.env.NODE_ENV='TESTING';
  const { FIREBASE_UID } = require('dotenv').config()?.parsed;
  const { red, green, white } = require('chalk');
  const chai = require('chai');
  const chaiHttp = require('chai-http');
  const server = require('../lib/api').API;
  const should = chai.should();
  const expect = chai.expect;
  chai.use(chaiHttp);
  const test = chai.request(server).keepOpen();

  const shouldPrint = (details, status) => {
      return white(`details: ${details}, status: ${status}`);
  };

describe('Authorization Middleware Error Check for bad token', () => {

    it(shouldPrint('Bad Request', red(400)), async () => {
        try {
            const res = await test.get('/').send()
            res.should.have.status(400);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('Bad request')
            expect(status).to.equal(400)
        } catch (error) { 
            throw error 
        }
    })


    it(shouldPrint('Unauthorized', red(401)), async () => {
        try {
            const res = await test.get('/').set('Authorization', 'Bearer bad123token').send()
            res.should.exist
            res.should.have.status(401);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('Unauthorized')
            expect(status).to.equal(401) 
        } catch (error) {
            throw error
        }
    })

}

 describe('Get token and ping', () => {
    let adminToken

    it(shouldPrint( 'Create custom jwt for testing', green(200)), async () => {
        try {
            const res = await test.get(`/createToken/${FIREBASE_UID}`).send()
            res.should.exist
            res.should.have.status(200);
            res.should.have.json
            adminToken = (JSON.parse(res.text)).token
        } catch (error) {
            throw error
        }
    })

    it(shouldPrint('PING', green(200)), async () => {
        try {
            const res = await test.get('/')
                .set('x-tenorders-testing', 'true')
                .set('Authorization', `Bearer ${adminToken}`).send()

            res.should.exist
            res.should.have.status(200);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('PING')
            expect(status).to.equal(200)
        } catch (error) {
            throw error
        }   
    })

}
`

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡