Hi,
So I''m stuck again with creating a mock for Net::SSH, I''ve
managed to
mock the call to Net::SSH.start and yield the Net::SSH mock but I am
totally stuck with mocking the session.shell.sync call and will also
need to mock the shell.send_command call also. Any help much
appreciated.
When I run the following spec I get the error:
Mock ''Net::SSH'' received unexpected message :shell with (no
args)
I''ve tried things like @shell = mock(Net::SSH::Service::Shell) but
this also gives an error complaining that Service doe snot exist.
# test code
@connection = Ssh::Remote.new
@ssh = mock(Net::SSH)
Net::SSH.should_receive(:start).and_yield(@ssh)
Net::SSH.should_receive(:shell).and_return(''something'')
# library code
require ''net/ssh''
module Ssh
class Remote
def remote_command(server, user, commands=[])
Net::SSH.start(server, user) do |session|
shell = session.shell.sync
commands.each do |command|
out = shell.send_command command[:command]
end
end
end
end
end
On 21 Apr 2008, at 07:03, Jamie D wrote:> Net::SSH.should_receive(:shell).and_return(''something'')This should be @ssh.should_receive(:shell).and_return(''something'') But actually it will need to return a mock with :sync stubbed for the line: shell = session.shell.sync Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/
On Mon, Apr 21, 2008 at 8:03 AM, Jamie D <jam5t3r.lists at gmail.com> wrote:> Hi, > > So I''m stuck again with creating a mock for Net::SSH, I''ve managed to > mock the call to Net::SSH.start and yield the Net::SSH mock but I am > totally stuck with mocking the session.shell.sync call and will also > need to mock the shell.send_command call also. Any help much > appreciated. >Don''t mock APIs you don''t own. http://rubyurl.com/53Y6 Instead - create a thin API around such APIs and have your app use that instead. Now you have an easily mockable API. Also make sure you have end-to-end tests that use Net::SSH without any mocking. Aslak> When I run the following spec I get the error: > Mock ''Net::SSH'' received unexpected message :shell with (no args) > > I''ve tried things like @shell = mock(Net::SSH::Service::Shell) but > this also gives an error complaining that Service doe snot exist. > > # test code > @connection = Ssh::Remote.new > @ssh = mock(Net::SSH) > Net::SSH.should_receive(:start).and_yield(@ssh) > Net::SSH.should_receive(:shell).and_return(''something'') > > # library code > require ''net/ssh'' > > module Ssh > class Remote > > def remote_command(server, user, commands=[]) > Net::SSH.start(server, user) do |session| > shell = session.shell.sync > commands.each do |command| > out = shell.send_command command[:command] > end > end > end > end > end > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Mon, Apr 21, 2008 at 8:03 AM, Jamie D <jam5t3r.lists at gmail.com> wrote:> Hi, > > So I''m stuck again with creating a mock for Net::SSH, I''ve managed to > mock the call to Net::SSH.start and yield the Net::SSH mock but I am > totally stuck with mocking the session.shell.sync call and will also > need to mock the shell.send_command call also. Any help much > appreciated. >Don''t mock APIs you don''t own. http://rubyurl.com/53Y6 Instead - create a thin API around such APIs and have your app use that instead. Now you have an easily mockable API. Also make sure you have end-to-end tests that use Net::SSH without any mocking. Aslak> When I run the following spec I get the error: > Mock ''Net::SSH'' received unexpected message :shell with (no args) > > I''ve tried things like @shell = mock(Net::SSH::Service::Shell) but > this also gives an error complaining that Service doe snot exist. > > # test code > @connection = Ssh::Remote.new > @ssh = mock(Net::SSH) > Net::SSH.should_receive(:start).and_yield(@ssh) > Net::SSH.should_receive(:shell).and_return(''something'') > > # library code > require ''net/ssh'' > > module Ssh > class Remote > > def remote_command(server, user, commands=[]) > Net::SSH.start(server, user) do |session| > shell = session.shell.sync > commands.each do |command| > out = shell.send_command command[:command] > end > end > end > end > end > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Thanks for the info Aslak, I have rewritten my code like you suggest
but have one issue with raising an exception. When I try the code in
the console an exception is raised correctly but in my test code I get
a message "command did not return expected result"
# test
describe Ssh, "Remote" do
before(:each) do
@ssh = mock(Net::SSH)
@response = mock(Net::SSH)
@connection = Ssh::Remote.new
@connection.should_receive(:start).with(''server'',
''root'').and_return(@ssh)
@connection.should_receive(:close)
@ssh.should_receive(:send_command).with(''ls
/'').and_return(@response)
@response.should_receive(:stdout).and_return(''a list'')
end
it "should raise exception if response does not match expected" do
@connection.remote_command(''server'',
''root'', [{:command => ''ls /'',
:expects => /blah/}]).
should raise_error(Ssh::CommandError, ''command did not return
expected result'')
end
end
# code exception.rb
module Ssh
class CommandError < Exception
end
end
# ssh.rb
require ''net/ssh''
require ''ssh/exception''
module Ssh
class Remote
def remote_command(server, user, commands=[])
shell = start(server, user)
commands.each do |command|
out = shell.send_command command[:command]
unless out.stdout =~ command[:expects] or command[:expects].blank?
close
raise(CommandError.new, ''command did not return expected
result'')
end
end
close
return true
end
def start(server, user)
@session = Net::SSH.start(server, user)
@session.shell.sync
end
def close()
@session.close
end
end
end
Thanks
Jamie
Fixed it, I was missing the lambda:
it "should raise exception if response does not match expected" do
lambda{ @connection.remote_command(''server'',
''root'', [{:command =>
''ls /'', :expects => /blah/}]) }.
should raise_error(Ssh::CommandError, ''command did not return
expected result'')
end
On 21/04/2008, Jamie D <jam5t3r.lists at gmail.com>
wrote:> Thanks for the info Aslak, I have rewritten my code like you suggest
> but have one issue with raising an exception. When I try the code in
> the console an exception is raised correctly but in my test code I get
> a message "command did not return expected result"
>
> # test
> describe Ssh, "Remote" do
>
> before(:each) do
> @ssh = mock(Net::SSH)
> @response = mock(Net::SSH)
> @connection = Ssh::Remote.new
> @connection.should_receive(:start).with(''server'',
''root'').and_return(@ssh)
> @connection.should_receive(:close)
> @ssh.should_receive(:send_command).with(''ls
/'').and_return(@response)
> @response.should_receive(:stdout).and_return(''a
list'')
> end
>
> it "should raise exception if response does not match expected"
do
> @connection.remote_command(''server'',
''root'', [{:command => ''ls /'',
> :expects => /blah/}]).
> should raise_error(Ssh::CommandError, ''command did not
return
> expected result'')
> end
>
> end
>
> # code exception.rb
> module Ssh
> class CommandError < Exception
> end
> end
>
> # ssh.rb
> require ''net/ssh''
> require ''ssh/exception''
>
>
> module Ssh
> class Remote
>
> def remote_command(server, user, commands=[])
>
> shell = start(server, user)
>
> commands.each do |command|
> out = shell.send_command command[:command]
>
> unless out.stdout =~ command[:expects] or command[:expects].blank?
> close
> raise(CommandError.new, ''command did not return expected
result'')
> end
> end
> close
> return true
> end
>
> def start(server, user)
> @session = Net::SSH.start(server, user)
> @session.shell.sync
> end
>
> def close()
> @session.close
> end
>
> end
> end
>
> Thanks
>
> Jamie
>