多个Angular请求会在测试中导致错误

时间:2017-10-02 23:53:47

标签: ruby-on-rails angularjs selenium testing capybara

我有一个带有Rails 4.0后端的Angular 1.5应用程序,我遇到了这个问题,在我的测试中,一旦工作人员登录3个查询同时发送到后端。在测试中(使用Capybara + selenium + chromeheadless),这会导致这些请求导致后端出错。在开发中它工作正常。

错误的一个例子;

NoMethodError at /entities/get_current_entity
=============================================

> undefined method `fields' for nil:NilClass

app/controllers/application_controller.rb, line 79
--------------------------------------------------

``` ruby
   74   
   75     private
   76   
   77     def set_locale
   78       #I18n.locale = params[:locale] if params[:locale].present?
>  79       if current_staff.nil? or current_staff.locale.nil?
   80         I18n.locale = "en"
   81       else
   82         I18n.locale = current_staff.locale
   83       end
   84     end
```

App backtrace
-------------

 - app/controllers/application_controller.rb:79:in `set_locale'
<Snip>

失败的测试

require "rails_helper"

RSpec.describe "Login", :type => :feature do
  describe "login with existing staff member" do
    before do 
      create_admin
    end

    it "logs in as admin" do
      visit "#/login"
      fill_in "Email", with: "admin@test.com.au"
      fill_in "Password", with: "password"
      click_button "Login"

      within "#staff-status" do
        expect(page).to have_text('LOGOUT')    
      end

      within("#flash-messages") do 
        expect(page).to have_text('Successful login')
      end

      # Check session variables
      within("#selected-entity") do 
        expect(page).to have_text("LOGIN DEFAULT COMPANY")
      end

      within("#selected-ledger") do 
        expect(page).to have_text("My Ledger")
      end

      within("#selected-division") do 
        expect(page).to have_text("1-General")
      end
    end
  end
end

以下是导致待处理调用的代码

  $scope.$on('devise:new-session', (event, currentStaff) ->
    # staff logged in by Auth.login({...})
    Auth.currentUser().then((staff) ->
      FirmService.current_entity($rootScope)
      DivisionService.current_division($rootScope)
      LedgerService.current_ledger($rootScope)

      $rootScope.current_staff = staff
    , (error) ->
      console.log("fail")
    )

    $location.path "/dashboard"
  )

这在整个应用程序中都会发生,并且在Rails 3.2上没有发生。只有在我升级到Rails 4之后才开始发生这种情况。

如果我使用promises,那么这个问题就不会发生。我不能总是使用promises来获取数据,这也会减慢应用程序的速度。

以下是登录的解决方法;

Auth.currentUser().then((staff) ->
  FirmService.current_entity($rootScope).then ->
    DivisionService.current_division($rootScope).then ->
      LedgerService.current_ledger($rootScope)

如何在测试模式下让Rails 4处理这样的多个请求?

更新:在测试环境中运行服务器

我在测试环境中运行我的服务器以尝试手动复制问题,但这样做时就可以了。所以它必须与测试的速度或水豚本身有关?

更新:更新了宝石

我更新了capybara 2.15.2,selenium-webdriver 3.6.0&amp; chromedriver-helper 1.1.0。这没有用。

更新:错误

有时错误会发生变化,即使用户成功登录,我的某个请求上的“员工未登录”也会出现错误。

更新:调试

将'require'pry“; binding.pry'插入到AngularJS调用结束的Rails控制器中,不能按预期工作。我在AngularJS代码中有三个调用,我希望Rails会三次调试调试行。我第一次使用调试行运行它时,它只触及其中一个,第二次它没有命中任何调试行。相反,我在/ entities / get_current_entity得到了NoMethodError,对于除法和分类帐也是如此。

更新:关注撬开

如果我将binding.pry放入set_locale方法并调用current_staff.locale.nil?我发现有时pry会永远挂起

在重新标记set_locale内容后,它继续并仍然失败,在test.log文件中我得到这些错误;

Completed 500 Internal Server Error in 4690ms
Completed 500 Internal Server Error in 4688ms
Completed 500 Internal Server Error in 4686ms

NoMethodError - undefined method `fields' for nil:NilClass:
<snip>
NoMethodError - undefined method `fields' for nil:NilClass:
<snip>
NoMethodError - undefined method `collect' for nil:NilClass:
<snip>
(1.3ms)  ALTER TABLE "indirect_taxes" DISABLE TRIGGER ALL;ALTER TABLE "ledger_defaults" DISABLE TRIGGER ALL;ALTER TABLE "ledgers" DISABLE TRIGGER ALL;ALTER TABLE "levels" DISABLE TRIGGER ALL;ALTER TABLE "locations" DISABLE TRIGGER ALL;ALTER TABLE "phones" DISABLE TRIGGER ALL;ALTER TABLE "sessions" DISABLE TRIGGER ALL;ALTER TABLE "transactions" DISABLE TRIGGER ALL;ALTER TABLE "versions" DISABLE TRIGGER ALL;ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "staff" DISABLE TRIGGER ALL;ALTER TABLE "tickets" DISABLE TRIGGER ALL;ALTER TABLE "timesheets" DISABLE TRIGGER ALL;ALTER TABLE "websites" DISABLE TRIGGER ALL;ALTER TABLE "customers" DISABLE TRIGGER ALL;ALTER TABLE "costings" DISABLE TRIGGER ALL;ALTER TABLE "disbursements" DISABLE TRIGGER ALL;ALTER TABLE "employees" DISABLE TRIGGER ALL;ALTER TABLE "entities" DISABLE TRIGGER ALL;ALTER TABLE "folios" DISABLE TRIGGER ALL;ALTER TABLE "work_descs" DISABLE TRIGGER ALL;ALTER TABLE "account_groups" DISABLE TRIGGER ALL;ALTER TABLE "accounts" DISABLE TRIGGER ALL;ALTER TABLE "addresses" DISABLE TRIGGER ALL;ALTER TABLE "business_types" DISABLE TRIGGER ALL;ALTER TABLE "charges" DISABLE TRIGGER ALL;ALTER TABLE "comments" DISABLE TRIGGER ALL;ALTER TABLE "invoices" DISABLE TRIGGER ALL;ALTER TABLE "jobs" DISABLE TRIGGER ALL;ALTER TABLE "divisions" DISABLE TRIGGER ALL;ALTER TABLE "emails" DISABLE TRIGGER ALL
   (411.5ms)  TRUNCATE TABLE "public"."indirect_taxes", "public"."ledger_defaults", "public"."ledgers", "public"."levels", "public"."locations", "public"."phones", "public"."sessions", "public"."transactions", "public"."versions", "public"."staff", "public"."tickets", "public"."timesheets", "public"."websites", "public"."customers", "public"."costings", "public"."disbursements", "public"."employees", "public"."entities", "public"."folios", "public"."work_descs", "public"."account_groups", "public"."accounts", "public"."addresses", "public"."business_types", "public"."charges", "public"."comments", "public"."invoices", "public"."jobs", "public"."divisions", "public"."emails" RESTART IDENTITY CASCADE;
   (1.9ms)  ALTER TABLE "indirect_taxes" ENABLE TRIGGER ALL;ALTER TABLE "ledger_defaults" ENABLE TRIGGER ALL;ALTER TABLE "ledgers" ENABLE TRIGGER ALL;ALTER TABLE "levels" ENABLE TRIGGER ALL;ALTER TABLE "locations" ENABLE TRIGGER ALL;ALTER TABLE "phones" ENABLE TRIGGER ALL;ALTER TABLE "sessions" ENABLE TRIGGER ALL;ALTER TABLE "transactions" ENABLE TRIGGER ALL;ALTER TABLE "versions" ENABLE TRIGGER ALL;ALTER TABLE "staff" ENABLE TRIGGER ALL;ALTER TABLE "tickets" ENABLE TRIGGER ALL;ALTER TABLE "timesheets" ENABLE TRIGGER ALL;ALTER TABLE "schema_migrations" ENABLE TRIGGER ALL;ALTER TABLE "websites" ENABLE TRIGGER ALL;ALTER TABLE "customers" ENABLE TRIGGER ALL;ALTER TABLE "costings" ENABLE TRIGGER ALL;ALTER TABLE "disbursements" ENABLE TRIGGER ALL;ALTER TABLE "employees" ENABLE TRIGGER ALL;ALTER TABLE "entities" ENABLE TRIGGER ALL;ALTER TABLE "folios" ENABLE TRIGGER ALL;ALTER TABLE "work_descs" ENABLE TRIGGER ALL;ALTER TABLE "account_groups" ENABLE TRIGGER ALL;ALTER TABLE "accounts" ENABLE TRIGGER ALL;ALTER TABLE "addresses" ENABLE TRIGGER ALL;ALTER TABLE "business_types" ENABLE TRIGGER ALL;ALTER TABLE "charges" ENABLE TRIGGER ALL;ALTER TABLE "comments" ENABLE TRIGGER ALL;ALTER TABLE "invoices" ENABLE TRIGGER ALL;ALTER TABLE "jobs" ENABLE TRIGGER ALL;ALTER TABLE "divisions" ENABLE TRIGGER ALL;ALTER TABLE "emails" ENABLE TRIGGER ALL

我认为使用Truncate表的最后一点是数据库清理程序试图清理混乱。所以我得到的那三个服务器错误似乎超时了。为什么数据库/ Rails会停止监听查询?

当我输入一个简单的查询时,

pry也会在set_locale方法中挂起

Staff.all

更新:strace输出

我从pry挂起时取得了strace输出; https://gist.github.com/map7/f25f75457f1a6ae6995934e2c2744660

1 个答案:

答案 0 :(得分:1)

聊了一会后,事实证明正在使用一个用于共享多个线程之间的数据库连接的补丁。问题是,这可能会产生多个同时发出的请求的各种问题,并且通常会导致测试中的潜在瑕疵。删除补丁修复了测试。

一旦您一路迁移到Rails 5.1,Rails就会通过互斥体处理测试环境中的连接共享,从而允许进行事务性功能测试,并且无需使用database_cleaner