Ruby: mocking file writes with Flexmock - ruby

Apologies if this was asked before.
A simple class:
class AskSO
def initialize( filehandle )
#filehandle = filehandle
end
def library_start
#filehandle << '<plist version="1.0">'
end
end
A simple unit test using Flex mock
require 'rubygems'
require 'flexmock/test_unit'
require 'AskSO'
require 'test/unit'
class AskSOTest < Test::Unit::TestCase
def setup
#filehandle = flexmock( "filehandle", "<<" => "" )
end
def test_library_start
#filehandle.should_receive( "<<" ).with( '<plist version="1.0">' ).once
#AskSOInstance = AskSO.new( #filehandle )
#AskSOInstance.library_start
end
end
When I run it with ruby AskSO-test.rb I get
1) Failure:
test_library_start(AskSOTest)
[/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/validators.rb:40:in `validate'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation.rb:123:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation.rb:122:in `each'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation.rb:122:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation_director.rb:64:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation_director.rb:63:in `each'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/expectation_director.rb:63:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/core.rb:76:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/core.rb:75:in `each'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/core.rb:75:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/core.rb:191:in `flexmock_wrap'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/core.rb:74:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/mock_container.rb:40:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/mock_container.rb:39:in `each'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/mock_container.rb:39:in `flexmock_verify'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/mock_container.rb:32:in `flexmock_teardown'
/Library/Ruby/Gems/1.8/gems/flexmock-0.9.0/lib/flexmock/test_unit.rb:26:in `teardown']:
in mock 'filehandle': method '<<("<plist version=\"1.0\">")' called incorrect number of times.
<1> expected but was
<0>.
What am I doing wrong? thanks in advance

Answering my own question in case someone else stumbles on the same problem - changed the mock definition to
def setup
#filehandle = flexmock( "filehandle" )
end
i.e., without the method. For same reason this solves the problem

Related

Dependency Injection causing both Rspec failure and IRB failure

Note: I am a Ruby and programming novice.
I have a class called JourneyLog I am trying to get a method called start to instantiate a new instance of another class, called Journey
class JourneyLog
attr_reader :journey_class
def initialize(journey_class: Journey)
#journey_class = journey_class
#journeys = []
end
def start(station)
journey_class.new(entry_station: station)
end
end
When I go into irbi get the following issue
2.2.3 :001 > require './lib/journeylog'
=> true
2.2.3 :002 > journeylog = JourneyLog.new
NameError: uninitialized constant JourneyLog::Journey
from /Users/BartJudge/Desktop/Makers_2018/oystercard-challenge/lib/journeylog.rb:4:in `initialize'
from (irb):2:in `new'
from (irb):2
from /Users/BartJudge/.rvm/rubies/ruby-2.2.3/bin/irb:15:in `<main>'
2.2.3 :003 >
I also have the following Rspec test
require 'journeylog'
describe JourneyLog do
let(:journey) { double :journey, entry_station: nil, complete?: false, fare: 1}
let(:station) { double :station }
let(:journey_class) { double :journey_class, new: journey }
describe '#start' do
it 'starts a journey' do
expect(journey_class).to receive(:new).with(entry_station: station)
subject.start(station)
end
end
end
I get the following Rspec failure;
1) JourneyLog#start starts a journey
Failure/Error: expect(journey_class).to receive(:new).with(entry_station: station)
(Double :journey_class).new({:entry_station=>#<Double :station>})
expected: 1 time with arguments: ({:entry_station=>#<Double :station>})
received: 0 times
# ./spec/jorneylog_spec.rb:9:in `block (3 levels) in <top (required)>'
I am at a total loss on what the problem is, or where to look for some answers.
I'm assuming I'm not injecting the Journey class properly, but thats as far as I can get myself.
Could someone provide some assistance?
In the journeylog.rb file you need to load the Journey class:
require 'journey' # I guess the Journey class is defined in lib/journey.rb
In the spec file you need to pass journey_class to the JourneyLog constructor:
describe JourneyLog do
subject { described_class.new(journey_class: journey_class) }
# ...

undefined method 'execute' for nil:NilClass

I am making a tool in ruby which can interact with databases.
I am using amalgalite as an adapter for sqlite3.
Code:
require 'amalgalite'
# this is class RQuery
class RQuery
def db_open(db_name)
#db = Amalgalite::Database.new "#{db_name}.db"
make_class
end
def exec_this(query)
#db.execute(query)
end
def make_class
tables_list = exec_this("select name from sqlite_master where type='table'")
tables_list.each do |table|
#class_created = Object.const_set(table[0].capitalize, Class.new)
#class_created.class_eval do
define_singleton_method :first do
RQuery.new.exec_this("select * from #{table[0]} order by #{table[0]}.id ASC limit 1")
end
end
end
end
def eval_this(input)
instance_eval(input)
end
def code
print '>>'
input = gets
exit if input =~ /^q$/
puts eval_this(input)
code
end
end
Now when I am running the code everything works fine until I call table_name.first
It gives output
vbhv#fsociety ~/git/R-Query/bin $ ruby main.rb
Enter the code or q for quit
>>db_open('vbhv')
users
persons
people
programmers
>>Users.first
/home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval': undefined method `execute' for nil:NilClass (NoMethodError)
Did you mean? exec
from /home/vbhv/git/R-Query/lib/r-query.rb:29:in `block (3 levels) in make_class'
from (eval):1:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:43:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from main.rb:4:in `<main>'
Now the 'execute' function it is talking about is inside amalgalite. What am I doing wrong here?? Thanks in Advance!
The problem in this was that the new class formed dynamically doesn't know about the connection variable '#db'. Hence the code solves the problem.
#class_created.instance_variable_set(:#database, #db)
A big thanks to Jagdeep Singh.

Rspec validation of method definition - Failure/Error

In Rspec, testing whether an instance is able to call method x.
DockingStation.rb
class DockingStation
def release_bike
end
end
Docking_spec.rb
require_relative '../lib/DockingStation'
describe DockingStation do
before(:each) do
#dockstat = DockingStation.new
end
describe "#DockingStation" do
it "Check release method" do
expect(#dockstat).to respond_to(:release_bike)
end
end
end
Currently getting the following error message:
1) DockingStation#DockingStation Check release method
Failure/Error: expect(#dockstat).to respond_to(:release_bike)
expected #<DockingStation:0x007fa518a6da00> to respond to :release_bike
# ./spec/Docking_spec.rb:10:in `block (3 levels) in <top (required)>'
What I'm expecting is for the object #dockstat instantiated in the Docking_spec.rb to respond to the release_bike method defined in DockingStation.rb, but this is not the case.
require_relative '../DockingStation'

How to POST data in Rack::Test

i'm having problems understanding how to work with Rack::Test, the issue i have is with POST. This are the classes and the error:
hellotesting.rb
require 'sinatra'
post '/foo' do
"Hello #{params[:name]}."
end
This is the test:
require 'hellotesting'
require 'test/unit'
require 'rack/test'
set :environment, :test
class HelloWorldTest < Test::Unit::TestCase
def test_it_says_hello_to_you
browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application))
post "/foo", "name" => "Bryan"
assert browser.last_response.ok?
assert_equal 'Hello Bryan', browser.last_response.body
end
end
And the output:
1) Error:
test_it_says_hello_to_you(HelloWorldTest):
ArgumentError: wrong number of arguments (1 for 0)
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1141:in `name'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1141:in `send'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1141:in `compile!'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1141:in `each_pair'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1141:in `compile!'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1129:in `route'
/Library/Ruby/Gems/1.8/gems/sinatra-1.2.6/lib/sinatra/base.rb:1118:in `post'
(__DELEGATE__):3:in `send'
(__DELEGATE__):3:in `post'
testingjeison.rb:11:in `test_it_says_hello_to_you'
It may be that you need to include the Rack::Test mixins into your individual classes. I mainly use RSpec, which doesn't use classes, but does use a specialized variant of Ruby's include for pulling in extra functionality. You may want to try putting in include Rack::Test::Methods inside your HelloWorldTest case class definition. Sinatra's testing has more information for testing with Rack::Test.

Ruby error with CSV and <<

Well, I think the code speaks out for itself :)
# book_in_stock.rb
class BookinStock
attr_reader :isbn, :price
def initialize(isbn, price)
#isbn = isbn
#price = Float(price)
end
end
# csv_reader.rb
require 'csv'
class CsvReader
def initialize
#book_in_stock = []
end
def read_in_csv_data(csv_file_name)
CSV.foreach(csv_file_name, headers: true) do |row|
#books_in_stock << BookinStock.new(row["ISBN"], row["Amount"])
end
end
# later we'll see how to use inject to sum a collection
def total_value_in_stock
sum = 0.0
#books_in_stock.each { |book| sum += book.price }
sum
end
def number_of_each_isbn
# ...
end
end
# stock_stats.rb
reader = CsvReader.new()
ARGV.each do |csv_file_name|
STDERR.puts "[+] Processing #{csv_file_name}"
reader.read_in_csv_data(csv_file_name)
end
puts "[+] Total value = #{reader.total_value_in_stock}"
When running I get:
# +search/pickaxe/csv $ ruby1.9.1 test.rb data.csv
# [+] Processing data.csv
# test.rb:23:in `block in read_in_csv_data': undefined method `<<' for nil:NilCla
# ss (NoMethodError)
# from /usr/lib/ruby/1.9.1/csv.rb:1760:in `each'
# from /usr/lib/ruby/1.9.1/csv.rb:1196:in `block in foreach'
# from /usr/lib/ruby/1.9.1/csv.rb:1334:in `open'
# from /usr/lib/ruby/1.9.1/csv.rb:1195:in `foreach'
# from test.rb:22:in `read_in_csv_data'
# from test.rb:46:in `block in <main>'
# from test.rb:44:in `each'
# from test.rb:44:in `<main>'
What've I done wrong?
'#books_in_stock' != '#book_in_stock' # !
(typo)
You have a typo in the initialize function (#book_in_store insteadn of #books_in_store). Is that it?
By the way, the sum of the prices can be done with inject in one line
#books_in_stock.inject(0) { |sum, book| sum + book.price }
If you run the command with ruby -w, it'll turn on warnings, and the interpreter will explain what went wrong:
$ ruby -w book_in_stock.rb
book_in_stock.rb:28: warning: instance variable #books_in_stock not initialized
book_in_stock.rb:28:in `total_value_in_stock': undefined method `each' for nil:NilClass (NoMethodError)
from book_in_stock.rb:47:in `<main>'

Resources