2015-06-06 18 views
6

tôi có một phần của mã được sử dụng node-sync như vậy:kiểm tra mã đồng bộ

function funcA() { 
    return new Promise(function(resolve, reject) { 
    Sync(function() { 
     return funcB.sync(); 
    }, function (err, result) { 
     if(err) { 
     reject(err); 
     } else { 
     resolve(result); 
     } 
    }); 
} 

Mã này được thử nghiệm sử dụng mocha + chai:

it("should return array", function() { 
    return funcA().then(function(result) { 
    expect(result).to.be.an.instanceof(Array); 
    }); 
}); 

Nó làm việc vài chỉ Phạt tiền months ago , nhưng bây giờ thử nghiệm này luôn luôn hết thời gian:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Điều tôi đã thử cho đến thời điểm này:

  • sử dụng done() thay vì trả lại một lời hứa
  • thay thế node-sync với synchronize.js
  • tăng timeout

gì tôi phát hiện ra, được rằng expect(... phần của thử nghiệm này là, trên thực tế, được gọi , nhưng chỉ sau khi mocha giết chết thử nghiệm. Bất kể khoảng thời gian chờ nào hiện được đặt, expect(.. luôn được gọi là ~ 20 mili giây sau khi tôi nhận được thông báo Error: timeout.

Tôi đã khắc phục sự cố bằng cách thêm setInterval(function(){}, 10) vào đầu tệp thử nghiệm. Tôi muốn biết tại sao điều này lại hiệu quả và nếu có cách nào tốt hơn để khắc phục điều đó?

[EDIT] Dường như đây là vấn đề cụ thể về phiên bản nút. Kiểm tra không thành công trên 0.12.4 nhưng chạy đúng 0.10.38.

[EDIT] Mã thực tế có sẵn here.

+1

Dường như rất lạ .. tôi có thể tái sản xuất nhưng không thể tìm ra vấn đề là gì. có thể là một shot dài nhưng có thể đào vào nút đồng bộ, xem các vé github [ở đây] (https://github.com/ybogdanov/node-sync/issues/41) và [ở đây] (https: // github. com/ybogdanov/node-sync/issues/36) –

+0

btw thường là cách thực hành tốt nhất (imho) để không chạy mã không đồng bộ trong một thử nghiệm. Tôi biết bạn đang cố gắng để chạy đồng bộ khối này, nhưng có thể thử mô-đun-như-hứa để bạn có thể loại bỏ 'done' –

Trả lời

1

Bạn có thể chỉ được thiếu done() callback:

it("should return array", function(done) { 
    funcA().then(function(result) { 
     expect(result).to.be.an.instanceof(Array); 
     done(); 
    }); 
}); 

http://mochajs.org/#asynchronous-code

+0

Hey, cảm ơn gợi ý - như đã đề cập trong câu hỏi tôi đã thử' done() '. Ngoài ra, trả lại lời hứa sẽ chỉ hoạt động tốt (trên thực tế bạn đã liên kết với phần rất trong tài liệu mocha, nơi được mô tả). Vấn đề của tôi dường như liên quan đến phiên bản nút. –

2

Dựa trên code của bạn, tôi giả định rằng chức năng funcB của bạn đang chạy mã trong một cách đồng bộ .

Vì vậy, khi tôi tạo funcB theo cách này:

function funcB() { 
    return [1, 2, 3]; 
} 

Và chạy thử nghiệm, Mocha cho thấy một lỗi:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Nhưng nếu tôi chuyển đổi funcB trong asynchronus chức năng như thế này :

function funcB(cb) { 
    process.nextTick(function() { 
    cb(null, [1, 2, 3]); 
    }); 
} 

Mocha chạy thử nghiệm mà không gặp bất kỳ sự cố nào:

✓ should return an array


Vì vậy, mã hoàn chỉnh của tôi chạy ok (các funcB nhận xét là một trong đó sẽ gây ra lỗi) được điều này:

// install dependencies 
// npm install promise 
// npm install sync 
var Promise = require('promise'); 
var assert = require('assert'); 
var Sync = require('sync'); 

function funcA() { 
    return new Promise(function (resolve, reject) { 
    Sync(function() { 
     return funcB.sync(); 
    }, function (err, result) { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(result); 
     } 
    }); 
    }); 
} 

// function funcB() { 
// return [1, 2, 3]; 
// } 

function funcB(cb) { 
    process.nextTick(function() { 
    cb(null, [1, 2, 3]); 
    }); 
} 

it("should return an array", function(done) { 
    return funcA().then(
    function (result) { 
     console.log(result); 
     assert.equal(Array.isArray(result), true); 
     done(); 
    } 
); 
}); 

Vì vậy, tôi ý kiến ​​tôi nghĩ rằng việc lạm dụng các sync method (sử dụng nó trên các chức năng đồng bộ) được tạo ra bởi thư viện đồng bộ là một trong đó gây ra vấn đề này.

+0

Hey Wilson! Cảm ơn bạn vì điều này, nhưng nó vẫn là một hack và nó không trả lời tại sao điều này xảy ra. Tôi đoán rằng việc sử dụng 'setInterval' của tôi phục vụ cùng một mục đích giống như hack' nextTick' của bạn. Dường như nút đó chuyển sang trạng thái "ngủ" và cần được đánh thức bởi 'nextTick' hoặc' setInterval'. Câu hỏi đặt ra là, tại sao điều này xảy ra và nếu đó là vấn đề về nút, sự cố Đồng bộ hóa hoặc hành vi mong đợi? Tôi rất muốn nhận được thông tin này. –

+0

Có lẽ tôi sai nhưng lý do từ tài liệu của [phương pháp] (https://github.com/ybogdanov/node-sync/blob/master/lib/sync.js#L27) có nội dung: * "sync() chỉ đơn giản là biến bất kỳ hàm không đồng bộ nào thành một hàm đồng bộ "* để gọi phương thức này từ một hàm đồng bộ hóa như funcB, với tôi có thể là nguồn gốc của lỗi. – Wilson

1

Bạn có thể sử dụng thông số hết thời gian chờ để thực thi mocha.

Ví dụ, nếu bạn muốn có một thời gian chờ 500 mili giây, chỉ cần thay đổi của bạn package.json tới:

"scripts": { 
    "test": "mocha specs --timeout 500 --require specs/helpers/chai.js" 
}, 

Và có lẽ lời hứa của bạn bị từ chối, vì vậy bạn phải gọi done sử dụng catch phương pháp.

it("should return array", function(done) { 
    return funcA().then(function(result) { 
     expect(result).to.be.an.instanceof(Array); 
     done(); 
    }).catch(done); 
}); 

Điều này cũng sẽ giúp bạn gỡ lỗi các lỗi cuối cùng có thể xảy ra trong mã lời hứa của bạn.

+0

Xin chào! Như đã đề cập trong câu hỏi, tôi đã thử tăng thời gian chờ - kiểm tra không thành công * luôn * ngay sau khi hết thời gian chờ (bất kể giá trị thời gian chờ là gì). Có bắt là một mẹo tốt, nhưng thử nghiệm này không thất bại, nó lần ra ngoài. –

+0

@KonradDzwinel Hmm .. Có vẻ như bạn đang cố thử nghiệm mã với lời hứa làm mọi thứ trong cùng một quy trình. Hãy thử thay đổi 'setTimeout()' thành 'process.nextTick();' và kiểm tra xem nó có hoạt động không.Ngoài ra, bạn có thể gửi mã của phương pháp bạn đang cố gắng kiểm tra không? – Tulio

+0

Xin chào! Toàn bộ điều có sẵn [ở đây] (https://github.com/kdzwinel/Proofreader). Các thử nghiệm vượt qua trên nút 0.10 nhưng không thành công trên 0.12. Tôi sẽ thử thay đổi setInterval thành nextTick sau này. Tôi đoán là nó sẽ hoạt động - câu hỏi là tại sao tôi phải kích hoạt đánh dấu tiếp theo bằng tay trong nút 0.12? –

Các vấn đề liên quan