Browser Runner를 사용하여 Mocha에서 비동기 테스트를 실행하고 있으며 Chai의 기대 스타일 어설 션을 사용하려고합니다.
window.expect = chai.expect;
describe('my test', function() {
it('should do something', function (done) {
setTimeout(function () {
expect(true).to.equal(false);
}, 100);
}
}
이것은 나에게 정상적인 실패한 주장 메시지를주지 않고 대신 나는 얻는다.
Error: the string "Uncaught AssertionError: expected true to equal false" was thrown, throw an Error :)
at Runner.fail (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3475:11)
at Runner.uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3748:8)
at uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3778:10)
따라서 분명히 오류를 포착하고 있으며 올바르게 표시하지 않습니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까? 오류 객체를 사용하여 “done”이라고 부를 수 있지만 Chai와 같은 것의 모든 우아함을 잃고 매우 투박해집니다.
답변
비동기 테스트는 실패한 경우 예외가 의 범위 외부로 throw expect()
되어 캡처 할 수없는 예외를 생성합니다 .it()
it()
표시되는 캡처 된 예외는 process.on('uncaughtException')
노드 아래 또는 window.onerror()
브라우저에서를 사용하여 캡처됩니다 .
이 문제를 해결하려면 예외를 첫 번째 매개 변수로 setTimeout()
호출하기 위해에서 호출 한 비동기 함수 내에서 예외를 캡처해야합니다 done()
. 또한 done()
성공을 나타 내기 위해 매개 변수없이 호출해야합니다 . 그렇지 않으면 테스트 함수가 완료되었음을 알리지 않았기 때문에 mocha가 시간 초과 오류를보고합니다.
window.expect = chai.expect;
describe( 'my test', function() {
it( 'should do something', function ( done ) {
// done() is provided by it() to indicate asynchronous completion
// call done() with no parameter to indicate that it() is done() and successful
// or with an error to indicate that it() failed
setTimeout( function () {
// Called from the event loop, not it()
// So only the event loop could capture uncaught exceptions from here
try {
expect( true ).to.equal( false );
done(); // success: call done with no parameter to indicate that it() is done()
} catch( e ) {
done( e ); // failure: call done with an error Object to indicate that it() failed
}
}, 100 );
// returns immediately after setting timeout
// so it() can no longer catch exception happening asynchronously
}
}
모든 테스트 케이스에서 그렇게하는 것은 DRY가 아니라 성가신 일이므로이를 수행하는 기능을 제공 할 수 있습니다. 이 함수를 호출합시다 check()
.
function check( done, f ) {
try {
f();
done();
} catch( e ) {
done( e );
}
}
으로 check()
다음과 같이 이제 비동기 테스트를 다시 작성할 수 있습니다 :
window.expect = chai.expect;
describe( 'my test', function() {
it( 'should do something', function( done ) {
setTimeout( function () {
check( done, function() {
expect( true ).to.equal( false );
} );
}, 100 );
}
}
답변
다음은 ES6 / ES2015 약속 및 ES7 / ES2016 async / await에 대한 통과 테스트입니다. 이 주제를 조사하는 모든 사람에게 멋진 업데이트 된 답변을 제공하기를 바랍니다.
import { expect } from 'chai'
describe('Mocha', () => {
it('works synchronously', () => {
expect(true).to.equal(true)
})
it('works ansyncronously', done => {
setTimeout(() => {
expect(true).to.equal(true)
done()
}, 4)
})
it('throws errors synchronously', () => {
return true
throw new Error('it works')
})
it('throws errors ansyncronously', done => {
setTimeout(() => {
return done()
done(new Error('it works'))
}, 4)
})
it('uses promises', () => {
var testPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello')
}, 4)
})
testPromise.then(result => {
expect(result).to.equal('Hello')
}, reason => {
throw new Error(reason)
})
})
it('uses es7 async/await', async (done) => {
const testPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello')
}, 4)
})
try {
const result = await testPromise
expect(result).to.equal('Hello')
done()
} catch(err) {
done(err)
}
})
/*
* Higher-order function for use with async/await (last test)
*/
const mochaAsync = fn => {
return async (done) => {
try {
await fn()
done()
} catch (err) {
done(err)
}
}
}
it('uses a higher order function wrap around async', mochaAsync(async () => {
const testPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello')
}, 4)
})
expect(await testPromise).to.equal('Hello')
}))
})
답변
약속이 마음에 들면 Chai as Promised + Q를 사용해보십시오 .
doSomethingAsync().should.eventually.equal("foo").notify(done);
답변
나는 Mocha 메일 링리스트에서 같은 것을 물었다. 그들은 기본적으로 이렇게 말했습니다. Mocha와 Chai로 비동기 테스트를 작성하기 위해 :
- 항상 테스트 시작
if (err) done(err);
- 항상
done()
.
그것은 내 문제를 해결했고 사이에 내 코드의 한 줄을 변경하지 않았습니다 (Chai 기대치). 이것은 setTimout
비동기 테스트를 수행하는 방법이 아닙니다.
다음 은 메일 링리스트에있는 토론 링크 입니다.
답변
이 문제를 해결하는 패키지를 게시했습니다.
먼저 check-chai
패키지를 설치하십시오 .
npm install --save check-chai
그런 다음 테스트에서 아래와 같이 도우미 기능 chai.use(checkChai);
을 사용하고 사용합니다 chai.check
.
var chai = require('chai');
var dirtyChai = require('dirty-chai');
var checkChai = require('check-chai');
var expect = chai.expect;
chai.use(dirtyChai);
chai.use(checkChai);
describe('test', function() {
it('should do something', function(done) {
// imagine you have some API call here
// and it returns (err, res, body)
var err = null;
var res = {};
var body = {};
chai.check(done, function() {
expect(err).to.be.a('null');
expect(res).to.be.an('object');
expect(body).to.be.an('object');
});
});
});
Per Chai가 비동기 Mocha 테스트로 작업하게하는 방법이 있습니까? 나는 이것을 NPM 패키지로 게시했습니다.
자세한 내용은 https://github.com/niftylettuce/check-chai 를 참조하십시오.
답변
chaiAsPromised를 사용해보세요! 뛰어난 이름을 갖는 것 외에도 다음과 같은 명령문을 사용할 수 있습니다.
expect(asyncToResultingValue()).to.eventually.equal(true)
확인할 수 있으며, Mocha + Chai에서 매우 잘 작동합니다.
답변
Jean Vincent의 답변 과 매우 관련이 있고 영감을 받아 그의 check
함수 와 유사한 도우미 함수를 사용 하지만 eventually
대신 호출합니다 (이것은 약속 된 차이의 명명 규칙과 일치하는 데 도움이됩니다). 임의의 수의 인수를 사용하여 원래 콜백에 전달하는 함수를 반환합니다. 이를 통해 테스트에서 추가 중첩 함수 블록을 제거하고 모든 유형의 비동기 콜백을 처리 할 수 있습니다. 여기 ES2015로 작성되었습니다.
function eventually(done, fn) {
return (...args) => {
try {
fn(...args);
done();
} catch (err) {
done(err);
}
};
};
사용 예 :
describe("my async test", function() {
it("should fail", function(done) {
setTimeout(eventually(done, (param1, param2) => {
assert.equal(param1, "foo"); // this should pass
assert.equal(param2, "bogus"); // this should fail
}), 100, "foo", "bar");
});
});