Ruby 中的异步单元测试

发布于 2024-09-16 04:02:28 字数 1425 浏览 8 评论 0原文

我正在测试一些使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

私野 2024-09-23 04:02:28

异步调用在 JS 单元测试中通常会出现问题。我过去已经通过阻塞主线程直到 XHR 调用成功来使 XHR 调用有效同步来解决这个问题。如何做到这一点取决于您的框架,我不熟悉 Harmony 和 RightJS。然而,逻辑看起来像这样:

  1. 重写您的 XHR 方法,以便它维护锁定/互斥体。锁可以是一个简单的布尔值。当任何 XHR 正在处理时,锁定将为 true,当没有 XHR 正在处理时,锁定将为 false
  2. 在测试中,在运行断言之前,添加一个执行 XHR 的循环,然后等待直到锁清除。
  3. 循环完成后,您将确定 XHR 已完成,并且可以运行断言。

这种方法的目的是避免修改代码,否则会使测试无效。不幸的是,这也意味着您无法测试返回值本身,但我认为这将是任何不修改代码的策略的警告。

另一种方法是实际异步运行测试——即。使用 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:

  1. Override your XHR method so that it maintains a lock/mutex. The lock can be a simple boolean. When any XHR is in process, the lock will be true, when no XHR is in process the lock will be false.
  2. In your test, before you run your assertion, add a loop that executes your XHR and then waits until the lock clears.
  3. Once the loop finishes, you'll be sure the XHR has completed, and you can run your assertion.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文