Создать спецификацию для модели с объединениями объединений - PullRequest
0 голосов
/ 21 марта 2019

как я могу сделать спецификацию для модели, которая вызывает метод соединения У меня есть этот код, но не работает, я получаю ошибки для метода соединения

def applicants_income_average
  users.joins(:financial_data).sum(:net_income_verified) /
  users.joins(:financial_data).where("financial_data.
    net_income_verified IS NOT NULL").size
end

context "#applicants_income_average" do
  before do
    user_a.build_financial_data(net_income_verified: 12_000)
    user_b.build_financial_data(net_income_verified: 13_000)

    allow(whitelabel).to receive(:users).and_return([user_a, user_b])
    allow(user_a).to receive(:join).and_return(user_a.financial_data)
    allow(user_b).to receive(:join).and_return(user_b.financial_data)
  end

  it "Should return 12_500" do
    expect(whitelabel.applicants_income_average).to eql(12_500)
  end
end

1 Ответ

0 голосов
/ 21 марта 2019

По общему признанию, может быть проще протестировать ActiveRecord через базу данных, чем имитировать, благодаря цепочке методов ActiveRecord.Но, если вы можете смириться с цепочечными операторами allow, ваши тесты будут намного быстрее, если вы будете издеваться над ActiveRecord.Кроме того, вы не будете тестировать то, что уже было тщательно протестировано основной командой Rails.

Вот как я мог бы подойти к решению проблемы выше.Я комментировал некоторые предположения и изменения, которые я сделал в коде.Надеюсь, это поможет!

class Whitelabel
  # I modified this for readability, but in the process discovered
  # that the same query could probably be used for both the numerator
  # and the denominator.
  def applicants_income_average
    sum_of_verified_net_income / count_of_users_with_verified_net_income
  end

  private

  def sum_of_verified_net_income
    users_with_verified_net_income.sum(:net_income_verified)
  end

  def count_of_users_with_verified_net_income
    users_with_verified_net_income.size
  end

  # Using a single query and memoizing the results will improve performance
  # This will also make it easier to test since we'll only call it once
  def users_with_verified_net_income
    @users_with_verified_net_income ||= do
      users
        .joins(:financial_data)
        .where('financial_data.net_income_verified IS NOT NULL')
    end
  end

  # I'm assuming this method must exist, given that the  
  # implementation of applicants_income_average referenced it
  def users
    User.where('some criteria')
  end
end

describe Whitelabel do
  subject(:whitelabel) { described_class.new }

  describe '#applicants_income_average' do
    subject(:applicants_income_average) { whitelabel.applicants_income_average }

    let(:users) { instance_double('users') }
    let(:users_with_financial_data) { instance_double('users_with_financial_data') }
    let(:users_with_verified_net_income) do
      instance_double('users_with_verified_net_income', sum: sum, size: size )
    end
    let(:sum) { 25000 }
    let(:size) { 2 }
    let(:average) { sum / size }

    before do
      allow(User).to receive(:where).and_return(users)
      allow(users).to receive(:joins).and_return(users_with_financial_data)
      allow(users_with_financial_data)
        .to receive(:where)
        .and_return(users_with_verified_net_income)
    end

    it 'selects the correct users' do
      applicants_income_average

      expect(User).to have_received(:where).with('some criteria')
    end

    it 'joins with financial data model' do
      applicants_income_average

      expect(users).to have_received(:joins).with(:financial_data)
    end

    it 'selects the users with verified net income' do
      applicants_income_average

      expect(users_with_financial_data)
        .to have_received(:where)
        .with('financial_data.net_income_verified IS NOT NULL')
    end

    it 'calculates average' do
      expect(applicants_income_average).to eq(average)
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...