2013-05-21 12 views
7

Moje pierwsze pytanie dotyczące Ruby. Próbuję przetestować interakcję EventMachine wewnątrz pętli reaktora - myślę, że można ją zakwalifikować jako "funkcjonalną".Testy Ruby EventMachine

Powiedz, że mam dwie klasy - serwer i klienta. Chcę przetestować obie strony - muszę mieć pewność co do ich interakcji.

Serwer:

require 'singleton' 

class EchoServer < EM::Connection 
    include EM::Protocols::LineProtocol 

    def post_init 
    puts "-- someone connected to the echo server!" 
    end 

    def receive_data data 
    send_data ">>>you sent: #{data}" 
    close_connection if data =~ /quit/i 
    end 

    def unbind 
    puts "-- someone disconnected from the echo server!" 
    end 
end 

Klient:

class EchoClient < EM::Connection 
    include EM::Protocols::LineProtocol 

    def post_init 
    send_data "Hello" 
    end 

    def receive_data(data) 
    @message = data 
    p data 
    end 

    def unbind 
    puts "-- someone disconnected from the echo server!" 
    end 
end 

Tak, próbowałem różnych podejść i wymyślił niczego.

Podstawowe pytanie brzmi: czy mogę jakoś przetestować mój kod za pomocą RSpec, używając should_recive?

Parametr EventMachine powinien być klasą lub modułem, więc nie mogę wysyłać instancji/wyśmiewać kodu wewnątrz. Dobrze?

Coś takiego?

describe 'simple rspec test' do 
    it 'should pass the test' do 
    EventMachine.run { 
     EventMachine::start_server "127.0.0.1", 8081, EchoServer 
     puts 'running echo server on 8081' 

     EchoServer.should_receive(:receive_data) 

     EventMachine.connect '127.0.0.1', 8081, EchoClient 

     EventMachine.add_timer 1 do 
     puts 'Second passed. Stop loop.' 
     EventMachine.stop_event_loop 
     end 
    } 
    end 
end 

A jeśli nie, jak zrobiłbyś to z EM :: SpecHelper? Używam tego kodu i nie wiem, co robię źle.

describe 'when server is run and client sends data' do 
    include EM::SpecHelper 

    default_timeout 2 

    def start_server 
    EM.start_server('0.0.0.0', 12345) { |ws| 
     yield ws if block_given? 
    } 
    end 

    def start_client 
    client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient) 
    yield client if block_given? 
    return client 
    end 

    describe "examples from the spec" do 
    it "should accept a single-frame text message" do 
     em { 
     start_server 

     start_client { |client| 
      client.onopen { 
      client.send_data("\x04\x05Hello") 
      } 
     } 
     } 
    end 
    end 
end 

Wypróbowałem wiele odmian tych testów i po prostu nie mogę tego rozgryźć. Jestem pewien, że czegoś tu brakuje ...

Dzięki za pomoc.

Odpowiedz

4

Najprostszym rozwiązaniem, które można myślę o to, aby to zmienić:

EchoServer.should_receive(:receive_data) 

do tego:

EchoServer.any_instance.should_receive(:receive_data) 

Od EM spodziewa klasę uruchomić serwer, powyższe any_instance trik będzie oczekiwać, że każda instancja tej klasy otrzyma tę metodę.

Przykład EMSpecHelper (choć jest oficjalny/standardowy) jest dość skomplikowany, wolałbym trzymać się pierwszego rspec i używać any_instance, tylko ze względu na prostotę.

+1

Działa. Jedną z rzeczy, o której należy pamiętać, jest to, że should_recive aktywuje tę metodę, więc działa tak, jakby w metodzie nie było niczego. Dzięki. – pfh

+0

http://axonflux.com/rspecs-shouldreceive-doesnt-ac – pfh

+1

Tak, RSpec obsługuje również [wywołanie oryginalnej metody ponownie] (https://www.relishapp.com/rspec/rspec-mocks/v/2- 12/docs/message-expectations/calling-the-original-method) od v2.12. – Subhas

Powiązane problemy