Ruby 中的异步单元测试
我正在测试一些使用 ruby 的 harmony 构建的 javascript 库。除了 AJAX 调用之外,一切都运行良好——有人知道如何实现这一点吗?
我的代码看起来像这样(我正在使用 RightJS):
my.js
function makerequest(argument) {
new Xhr('http://mysite.com/some/jsonp'),{
jsonp: true,
params: {something: argument},
onSuccess: function() {
// Calls a function defined outside my library
parse_response(this.json)
}
}).send()
}
< strong>test_makerequest.rb
require 'rubygems'
require 'harmony'
require 'test/unit'
require 'shoulda'
class RequestTest < Test::Unit::TestCase
context "The requesty thing" do
setup do
@page = Harmony::Page.new
@page.load(File.expand_path('js/my.js'))
end
should "get stuff from mysite.com" do
# Here I need to define a 'parse_response' which this
# should section will wait for and then do an 'assert'
# on the results.
results = callback_to_get_results_from__make_request
@page.execute('make_request("an argument")')
assert results == {'foo' => 'bar'}
end
end
end
所以是的,我的问题是,我应该如何分配上面的 results
以便我可以获得异步回调的结果?
I'm testing some javascript libraries I've built by using ruby's harmony. Everything is working perfectly except AJAX calls — does anyone have any ideas how to achieve this?
My code looks something like this (I'm using RightJS):
my.js
function makerequest(argument) {
new Xhr('http://mysite.com/some/jsonp'),{
jsonp: true,
params: {something: argument},
onSuccess: function() {
// Calls a function defined outside my library
parse_response(this.json)
}
}).send()
}
test_makerequest.rb
require 'rubygems'
require 'harmony'
require 'test/unit'
require 'shoulda'
class RequestTest < Test::Unit::TestCase
context "The requesty thing" do
setup do
@page = Harmony::Page.new
@page.load(File.expand_path('js/my.js'))
end
should "get stuff from mysite.com" do
# Here I need to define a 'parse_response' which this
# should section will wait for and then do an 'assert'
# on the results.
results = callback_to_get_results_from__make_request
@page.execute('make_request("an argument")')
assert results == {'foo' => 'bar'}
end
end
end
So yeah, my question is, how should I assign results
above such that I can get the results of the async callback?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
异步调用在 JS 单元测试中通常会出现问题。我过去已经通过阻塞主线程直到 XHR 调用成功来使 XHR 调用有效同步来解决这个问题。如何做到这一点取决于您的框架,我不熟悉 Harmony 和 RightJS。然而,逻辑看起来像这样:
true
,当没有 XHR 正在处理时,锁定将为false
。这种方法的目的是避免修改代码,否则会使测试无效。不幸的是,这也意味着您无法测试返回值本身,但我认为这将是任何不修改代码的策略的警告。
另一种方法是实际异步运行测试——即。使用 AOP 将您的断言附加到 onSuccess 回调。然而,许多测试套件不能很好地处理异步测试,因为一个测试的设置可能在前一个测试的拆卸之前开始(即因为前一个测试仍在等待异步调用返回)。
最后一种方法是模拟所有异步调用。 IE。只需覆盖 XHR 并让您的测试断言它是使用正确的参数调用的。如果我有确实经过整个异步堆栈的集成测试,我可能会喜欢这种方法。
Async calls are generally problematic with JS unit testing. I've solved it in the past by making the XHR calls effectively synchronous by blocking the main thread until the XHR call succeeds. How to do this varies depending on your framework, and I'm unfamiliar with Harmony and RightJS. However, the logic would look something like this:
true
, when no XHR is in process the lock will befalse
.The intent of this approach is to avoid modifying your code, which would invalidate your tests. Unfortunately, this also means you can't test the return value itself, but I think this will be a caveat of any strategy that doesn't modify your code.
Another approach would be to actually run your tests asynchronously--ie. attach your assertion to the onSuccess callback using AOP. However, many testing suites don't play nicely with asynchronous tests, since the setup of one test may be starting before the teardown of the previous test (ie. because the previous test is still waiting for the async call to return).
One last approach would be to mock all asynchronous calls. Ie. just override XHR and have your test assert that it was called with the right arguments. I might favor this approach if I have integration tests that do go through the whole async stack.