Рельсы RSpe c net -s sh пробный возврат второго s sh запроса - PullRequest
0 голосов
/ 04 февраля 2020

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

Проблема, с которой я сталкиваюсь в настоящее время, заключается в том, что я не могу смоделировать запрос с помощью моего ssh_with_stderr метода. Метод ssh отлично работает.

Этот код я пытаюсь проверить:

# app/jobs/zip_files_sync_job.rb

class ZipFilesSyncJob < ApplicationJob
  queue_as :default
  discard_on ActiveJob::DeserializationError

  def perform(simulation)
    simulation.zip_files.each do |f|
      if f.path.nil? && f.created_at < 6.hours.ago
        f.state = 'error'
        f.save!
        next
      end
      next if f.path.nil?

      _, errors = simulation.server.ssh_with_stderr("ls #{f.path.shellescape}")
      if errors.blank?
        f.size = f.simulation.server.ssh("stat -c %s #{f.path.shellescape}")
        f.state = 'ready' if f.size.to_i.positive?
      elsif f.state == 'ready' && errors.present?
        f.state = 'error'
      elsif f.state == 'zipping' && errors.present? && f.created_at < 6.hours.ago
        f.state = 'error'
      end
      f.save!
    end
  end
end

И вот что я хочу проверить:

# spec/jobs/zip_files_sync_job_spec.rb

require 'rails_helper'

RSpec.describe ZipFilesSyncJob, type: :job do
  let(:private_group) { Group::PRIVATE }
  let(:user) { FactoryBot.create :user }
  let(:server) { FactoryBot.create :server, user: user, external_storage: false }
  let(:simulation) { FactoryBot.create :simulation, user: user, group: private_group, server: server }
  let(:zip_file) { FactoryBot.create :zip_file, simulation: simulation, path: 'test/zip_file', state: 'pending', size: '100' }
  let(:zip_file_no_path) { FactoryBot.create :zip_file, simulation: simulation, path: nil, created_at: 10.hours.ago, state: 'pending' }
  let(:ssh_connection) { double('net-ssh') }

  before do
    zip_file_no_path
    allow(Net::SSH).to receive(:start).and_yield(ssh_connection)
  end

  def perform_zip_file_sync(zip_file)
    perform_enqueued_jobs do
      ZipFilesSyncJob.perform_now(simulation)
    end
    zip_file.reload

    yield

    allow(Net::SSH).to receive(:start).and_call_original
  end

  describe '#perform' do
    include ActiveJob::TestHelper

   #################################
   ##### This test works fine #####
   #################################

    context 'with no errors' do
      before do
        zip_file
      end
      it 'it will change the state to ready' do
        allow(Net::SSH).to receive(:start).and_return('144371201')
        perform_zip_file_sync(zip_file) do
          expect(zip_file.state).to eq 'ready'
        end
      end
    end

   #############################################################################
   ##### This test fails because it does not return on the ssh_with_stderr #####
   #############################################################################

    context 'with errors' do
      it 'will change the state to error' do
        allow(Net::SSH).to receive(:start).and_return("[' ', 'Error with connection']")
        perform_enqueued_jobs do
          ZipFilesSyncJob.perform_now(simulation)
        end
        zip_file.reload
        expect(zip_file.state).to eq 'error'
      end
    end
  end
end

Это код для подключения к серверу. Он использует net-ssh драгоценный камень

# app/models/server.rb

Class Server < ApplicationRecord

  def ssh(command, storage = true, &block)
    Net::SSH.start(hostname, username, port: port, keys: ["key"], non_interactive: true, timeout: 1) do |ssh|
      ssh.exec! "cd #{folder.shellescape}; #{command}", &block
    end
  end

  def ssh_with_stderr(command)
    @output = ""
    @errors = ""
    begin
      Net::SSH.start(hostname, username, port: port, keys: ["key"], non_interactive: true, timeout: 1) do |ssh|
        ssh.exec! "cd #{folder.shellescape}; #{command}" do |_ch, stream, data|
          if stream == :stderr
            @errors += data
          else
            @output += data
          end
        end
      end
    rescue Net::SSH::Exception, Errno::ECONNREFUSED, Errno::EINVAL, Errno::EADDRNOTAVAIL => e
      @output = nil
      @errors = e.message
     end
    [@output, @errors]
  end

1 Ответ

0 голосов
/ 04 февраля 2020

С этим макетом

allow(Net::SSH).to receive(:start).and_return("[' ', 'Error with connection']")

ssh_with_stderr выглядит как

def ssh_with_stderr(command)
  @output = ""
  @errors = ""
  begin
    [' ', 'Error with connection']
  rescue Net::SSH::Exception, Errno::ECONNREFUSED, Errno::EINVAL, Errno::EADDRNOTAVAIL => e
    @output = nil
    @errors = e.message
   end
  [@output, @errors]
end 

Так что он всегда возвращает ["",""], а проверка errors.blank? всегда положительна.

Попробуйте издеваться Net::SSH с and_raise вместо and_return, что-то вроде

allow(Net::SSH).to receive(:start).and_raise(Errno::ECONNREFUSED, "Error with connection")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...