在用 jasmine 测试我的代码时,我注意到了一个奇怪的行为。与我规范中的其他测试一起执行时,一项测试失败。当单独调用时,测试通过。
测试断言脚本 A.js 依赖于提供“创建”方法的脚本 B.js。我在测试中为“Create”创建了一个间谍并调用脚本 A.js (A.init),它将加载一些数据(loadData 再次返回一个 promise),然后调用“Create”方法 5 次(一旦 loadData -promise 已解决)。A.init() 返回另一个承诺!
当我使用 Jasmine 的“运行”方法并等到 promise-init 解决时,我喜欢断言 B.Create 被调用了 5 次。
在执行测试时,同一规范中的其他一些测试将为 B.Create 方法设置自己的间谍。所以我认为这会产生某种竞争条件。
注释:每个测试为 create-method ( ) 创建自己的 spy var createSpy = spyOn(B, "Create"
;
所以一切都归结为以下问题:
- 我是否面临竞争条件?
- 我该如何防止这个问题?时间模拟(jasmine.Clock.useMock)不是一个真正的解决方案,因为我用假冒伪劣模拟“loadData”方法。
Update-1:Richard Dingwall 在他的文章Parallel vs serial javascript async tests中概述了 Jasmine 并行执行测试,所以这是我问题的根源吗?
Update-2 这是失败的测试:
/* more code */
crmRestKitCreateSpy = spyOn( CrmRestKit, 'Create' )
.andCallFake( function ( entitySchemaName, obj ) {
return {
then: function ( callback ) {
// fake a create response where the id attribute is populated
callback( _.extend( {}, obj, { AccountId: cloneId } ) );
}
};
} );
/* more code */
it( 'links all child-clones to the new parent-clone', function () {
// arrange - inject spy
spyOn( CrmRestKit, 'ByQueryAll' ).andReturn(
alfa.fake.promise.buildFakeResolvePromise( { d: fakeChildAcccounts, __next: false }, 750 )
);
// arrange
includedOneToManyRel = [accountToAccountRel];
// action
var promise = alfa.util.clonemachine.deepClone( fakeId, includedOneToManyRel );
waitsFor( function () {
return promise.state() === 'resolved';
}, 800 );
runs( function () {
expect( crmRestKitCreateSpy.callCount ).toBe( 5 );
// assert - all child-clones reference the new parent-clone
expect( crmRestKitCreateSpy.calls[1].args[1].ParentAccountId.Id ).toBe( cloneId );
expect( crmRestKitCreateSpy.calls[2].args[1].ParentAccountId.Id ).toBe( cloneId );
expect( crmRestKitCreateSpy.calls[3].args[1].ParentAccountId.Id ).toBe( cloneId );
expect( crmRestKitCreateSpy.calls[4].args[1].ParentAccountId.Id ).toBe( cloneId );
} );
});
Update-3 我认为找到了我面临竞争条件的证据。以下测试通过。所以我的测试受到其他正在运行的测试的影响。
it( 'its a trape', function () {
waitsFor( function () {
return ( crmRestKitCreateSpy.callCount > 0 );
}, 4000 );
runs( function () {
expect( crmRestKitCreateSpy.callCount ).toBeGreaterThan( 0 );
} );
} );