programing tip

모카와 차이로 약속을 올바르게 테스트하려면 어떻게해야합니까?

itbloger 2020. 6. 21. 20:11
반응형

모카와 차이로 약속을 올바르게 테스트하려면 어떻게해야합니까?


다음 테스트는 이상하게 작동합니다.

it('Should return the exchange rates for btc_ltc', function(done) {
    var pair = 'btc_ltc';

    shapeshift.getRate(pair)
        .then(function(data){
            expect(data.pair).to.equal(pair);
            expect(data.rate).to.have.length(400);
            done();
        })
        .catch(function(err){
            //this should really be `.catch` for a failed request, but
            //instead it looks like chai is picking this up when a test fails
            done(err);
        })
});

거부 된 약속을 올바르게 처리하고 테스트하려면 어떻게해야합니까?

실패한 테스트를 어떻게 올바르게 처리해야합니까 (예 : expect(data.rate).to.have.length(400);?

테스트중인 구현은 다음과 같습니다.

var requestp = require('request-promise');
var shapeshift = module.exports = {};
var url = 'http://shapeshift.io';

shapeshift.getRate = function(pair){
    return requestp({
        url: url + '/rate/' + pair,
        json: true
    });
};

가장 쉬운 방법은 Mocha의 최신 약속 지원 내장 약속을 사용하는 것입니다.

it('Should return the exchange rates for btc_ltc', function() { // no done
    var pair = 'btc_ltc';
    // note the return
    return shapeshift.getRate(pair).then(function(data){
        expect(data.pair).to.equal(pair);
        expect(data.rate).to.have.length(400);
    });// no catch, it'll figure it out since the promise is rejected
});

또는 현대 노드와 async / await :

it('Should return the exchange rates for btc_ltc', async () => { // no done
    const pair = 'btc_ltc';
    const data = await shapeshift.getRate(pair);
    expect(data.pair).to.equal(pair);
    expect(data.rate).to.have.length(400);
});

이 접근 방식은 엔드 투 엔드 약속이므로 테스트하기가 더 쉬우 며 done()어디에서나 이상한 전화 처럼 생각하는 이상한 경우에 대해 생각할 필요가 없습니다 .

이것은 현재 Mocha가 Jasmine과 같은 다른 라이브러리보다 장점입니다. 당신은 또한 확인 할 수 있습니다 차이로이 약속 이 더 쉽게 (더하지 않습니다 것이다 .then)하지만 개인적으로는 현재 버전의 명확성과 단순성을 선호


이미 지적한 바와 같이 여기 , 모카의 최신 버전은 이미 약속-알고 있습니다. 그러나 OP가 Chai에 대해 구체적으로 물었으므로 chai-as-promised약속을 테스트하기위한 깔끔한 구문을 제공하는 패키지 를 지적하는 것이 공평합니다 .

약속 된 차이를 사용하여

약속의 약속을 사용 하여 약속에 대한 사례 resolvereject사례를 모두 테스트하는 방법은 다음과 같습니다 .

var chai = require('chai');
var expect = chai.expect;
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);

...

it('resolves as promised', function() {
    return expect(Promise.resolve('woof')).to.eventually.equal('woof');
});

it('rejects as promised', function() {
    return expect(Promise.reject('caw')).to.be.rejectedWith('caw');
});

약속 된 차이없이

테스트 대상에 대해 명확히하기 위해 다음과 같은 약속을 지키지 않고 동일한 예제를 작성했습니다.

it('resolves as promised', function() {
    return Promise.resolve("woof")
        .then(function(m) { expect(m).to.equal('woof'); })
        .catch(function(m) { throw new Error('was not supposed to fail'); })
            ;
});

it('rejects as promised', function() {
    return Promise.reject("caw")
        .then(function(m) { throw new Error('was not supposed to succeed'); })
        .catch(function(m) { expect(m).to.equal('caw'); })
            ;
});

여기 내 테이크가 있습니다 :

  • 사용 async/await
  • not needing extra chai modules
  • avoiding the catch issue, @TheCrazyProgrammer pointed out above

A delayed promise function, that fails, if given a delay of 0:

const timeoutPromise = (time) => {
    return new Promise((resolve, reject) => {
        if (time === 0)
            reject({ 'message': 'invalid time 0' })
        setTimeout(() => resolve('done', time))
    })
}

//                     ↓ ↓ ↓
it('promise selftest', async () => {

    // positive test
    let r = await timeoutPromise(500)
    assert.equal(r, 'done')

    // negative test
    try {
        await timeoutPromise(0)
        // a failing assert here is a bad idea, since it would lead into the catch clause…
    } catch (err) {
        // optional, check for specific error (or error.type, error. message to contain …)
        assert.deepEqual(err, { 'message': 'invalid time 0' })
        return  // this is important
    }
    assert.isOk(false, 'timeOut must throw')
    log('last')
})

Positive test is rather simple. Unexpected failure (simulate by 500→0) will fail the test automatically, as rejected promise escalates.

Negative test uses the try-catch-idea. However: 'complaining' about an undesired pass happens only after the catch clause (that way, it does not end up in the catch() clause, triggering further but misleading errors.

For this strategy to work, one must return the test from the catch clause. If you want't to test anything else, use another it()-block.


Thre is a better solution. Just return the error with done in a catch block.

// ...

it('fail', (done) => {
  // any async call that will return a Promise 
  ajaxJson({})
  .then((req) => {
    expect(1).to.equal(11); //this will throw a error
    done(); //this will resove the test if there is no error
  }).catch((e) => {
    done(e); //this will catch the thrown error
  }); 
});

this test will fail with following message: AssertionError: expected 1 to equal 11

참고URL : https://stackoverflow.com/questions/26571328/how-do-i-properly-test-promises-with-mocha-and-chai

반응형