Simple Rspec test fails - for what reason? - ruby

Coding one of my first rspec tests. headers == nil prints true, but the next test line headers should be_nil fails. Why?
require 'net/http'
$url_arr = []
$url_arr << ...
$url_arr << ...
$url_arr << ...
module NetHelpers
def get_headers(uri)
Net::HTTP.get_response(URI.parse(uri)).get_fields('Set-Cookie')
end
end
describe "new script" do
include NetHelpers
$url_arr.each do |uri|
it "should not return cookies" do
headers = get_headers(uri)
p "==========> #{headers == nil}"
headers should be_nil
end
end
end
Also, the output is
got: "new script" (using ==)
Why "new script" is printed, while headers really contains nil?

Try
headers.should be_nil
instead.

Related

RSpec why is before(:each) never executed?

I have this simple code
require 'json'
module Html
class JsonHelper
attr_accessor :path
def initialize(path)
#path = path
end
def add(data)
old = JSON.parse(File.read(path))
merged = old.merge(data)
File.write(path, merged.to_json)
end
end
end
and this spec (reduced as much as I could while still working)
require 'html/helpers/json_helper'
describe Html::JsonHelper do
let(:path) { "/test/data.json" }
subject { described_class.new(path) }
describe "#add(data)" do
before(:each) do
allow(File).to receive(:write).with(path, anything) do |path, data|
#saved_string = data
#saved_json = JSON.parse(data)
end
subject.add(new_data)
end
let(:new_data) { { oldestIndex: 100 } }
let(:old_data) { {"test" => 'testing', "old" => 50} }
def stub_old_json
allow(File).to receive(:read).with(path).and_return(#data_before.to_json)
end
context "when given data is not present" do
before(:each) do
puts "HERE"
binding.pry
#data_before = old_data
stub_old_json
end
it "adds data" do
expect(#saved_json).to include("oldestIndex" => 100)
end
it "doesn't change old data" do
expect(#saved_json).to include(old_data)
end
end
end
end
HERE never gets printed and binding.pry doesn't stop execution and tests fail with message No such file or directory # rb_sysopen - /test/data.json
This all means that before(:each) never gets executed.
Why?
How to fix it?
It does not print desired message because it fails at the first before block. Rspec doc about execution order
It fails because you provided an absolute path, so it is checking /test/data.json
Either use relative path to the test ie. ../data.json (just guessing),
or full path.
In case of rails:
Rails.root.join('path_to_folder_with_data_json', 'data.json')

Writing a test for a case statement in Ruby

I'm trying to write a test for a case statement using minitest. Would I need to write separate tests for each "when"? I included my code below. Right now it just puts statements, but eventually it's going to redirect users to different methods. Thanks!
require 'pry'
require_relative 'messages'
class Game
attr_reader :user_answer
def initialize(user_answer = gets.chomp.downcase)
#user_answer = user_answer
end
def input
case user_answer
when "i"
puts "information"
when "q"
puts "quitter"
when "p"
puts "player play"
end
end
end
This answer will help you. Nonetheless I'll post one way of applying it to your situation. As suggested by #phortx when initializing a game, override the default user-input with the relevant string. Then by using assert_output we can do something like:
#test_game.rb
require './game.rb' #name and path of your game script
require 'minitest/autorun' #needed to run tests
class GameTest < MiniTest::Test
def setup
#game_i = Game.new("i") #overrides default user-input
#game_q = Game.new("q")
#game_p = Game.new("p")
end
def test_case_i
assert_output(/information\n/) {#game_i.input}
end
def test_case_q
assert_output(/quitter\n/) {#game_q.input}
end
def test_case_p
assert_output(/player play\n/) {#game_p.input}
end
end
Running the tests...
$ ruby test_game.rb
#Run options: --seed 55321
## Running:
#...
#Finished in 0.002367s, 1267.6099 runs/s, 2535.2197 assertions/s.
#3 runs, 6 assertions, 0 failures, 0 errors, 0 skips
You have to test each case branch. Via RSpec it would work that way:
describe Game do
subject { Game }
describe '#input' do
expect_any_instance_of(Game).to receive(:puts).with('information')
Game.new('i').input
expect_any_instance_of(Game).to receive(:puts).with('quitter')
Game.new('q').input
expect_any_instance_of(Game).to receive(:puts).with('player play')
Game.new('p').input
end
end
However due the fact that puts is ugly to test, you should refactor your code to something like that:
require 'pry'
require_relative 'messages'
class Game
attr_reader :user_answer
def initialize(user_answer = gets.chomp.downcase)
#user_answer = user_answer
end
def input
case user_answer
when "i"
"information"
when "q"
"quitter"
when "p"
"player play"
end
end
def print_input
puts input
end
end
Then you can test with RSpec via:
describe Game do
subject { Game }
describe '#print_input' do
expect_any_instance_of(Game).to receive(:puts).with('quitter')
Game.new('q').print_input
end
describe '#input' do
expect(Game.new('i').input).to eq('information')
expect(Game.new('q').input).to eq('quitter')
expect(Game.new('i').input).to eq('player play')
expect(Game.new('x').input).to eq(nil)
end
end

rspec check 'with' argument is true

I have the following rspec example:
describe "with spike" do
it "succeeds" do
a = double('whatever')
a.should_receive(:b).with(true)
a.b('not false')
end
end
How can I make with accept any non-false argument?
Just write an arbitrary message handler:
describe "with spike" do
it "succeeds" do
a = double('whatever')
a.should_receive(:b) { |x|
x.should_not be_false
}
a.b('not false')
end
end

Rake caches rspec tests or what?

When I run rspec tests via rake task I get
1) Whois::Record::Parser::WhoisUa status_available.expected#created_on
Failure/Error: lambda { #parser.created_on }.should raise_error(Whois::PropertyNotSupported)
But my status_available_spec.rb looks like this:
# encoding: utf-8
# This file is autogenerated. Do not edit it manually.
# If you want change the content of this file, edit
#
# /spec/fixtures/responses/whois.ua/status_available.expected
#
# and regenerate the tests with the following rake task
#
# $ rake spec:generate
#
require 'spec_helper'
require 'whois/record/parser/whois.ua.rb'
describe Whois::Record::Parser::WhoisUa, "status_available.expected" do
before(:each) do
file = fixture("responses", "whois.ua/status_available.txt")
part = Whois::Record::Part.new(:body => File.read(file))
#parser = klass.new(part)
end
describe "#status" do
it do
#parser.status.should == :available
end
end
describe "#available?" do
it do
#parser.available?.should == true
end
end
describe "#registered?" do
it do
#parser.registered?.should == false
end
end
describe "#created_on" do
it do
#parser.created_on.should == nil
end
end
describe "#updated_on" do
it do
#parser.updated_on.should == nil
end
end
describe "#expires_on" do
it do
#parser.expires_on.should == nil
end
end
describe "#nameservers" do
it do
#parser.nameservers.should be_a(Array)
#parser.nameservers.should == []
end
end
end
and as you can see there is no .should raise_error(Whois::PropertyNotSupported) instead it was changed to .should == nil.
Is rake caching that stuff or what?

RSpec mock or stub super in a model

How do I test this tiny part of the module, with super? (superclass is action_dispatch-3.0.1 testing/integration...) The module is included within spec/requests to intercept post:
module ApiDoc
def post(path, parameters = nil, headers = nil)
super
document_request("post", path, parameters, headers) if ENV['API_DOC'] == "true"
end
...
end
I don't want it to run the ActionDispatch::Integration-whatever, but I don't know how to mock or stub super to unit test it.
The module is only used within specs, and will have 100% test coverage, which proves those kinds of metrics as useless. I need to unit test it.
An example, if needed, this is how I use the module ApiDoc
require 'spec_helper'
describe "Products API" do
include ApiDoc ############## <---- This is my module
context "POST product" do
before do
#hash = {:product => {:name => "Test Name 1", :description => "Some data for testing"}}
end
it "can be done with JSON" do
valid_json = #hash.to_json
############### the following 'post' is overriden by ApiDoc
post("/products.json",valid_json,
{"CONTENT_TYPE" => "application/json",
"HTTP_AUTHORIZATION" => ActionController::HttpAuthentication::Basic.encode_credentials("user", "secret")})
response.should be_success
end
end
end
You can check if the method is called on the 'super' class
ActionDispatch::Integration.any_instance.should_receive(:post)
Since ApiDock is only required for your tests you could also overwrite the post method with alias_method_chain:
ActionDispatch::Integration.instance_eval do
def post_with_apidoc(path, parameters = nil, headers = nil)
post_without_apidoc
if ENV['API_DOC'] == "true"
document_request("post", path, parameters, headers)
end
end
alias_method_chain :post, :apidoc
end
This is merely a supplement to the answer. This is how I ended up testing it
require 'spec_helper'
describe 'ApiDoc' do
include ApiDoc
it "should pass the post to super, ActionDispatch" do
#path = "path"
#parameters = {:param1 => "someparam"}
#headers = {:aheader => "someheaders"}
ActionDispatch::Integration::Session.any_instance.expects(:post).with(#path, #parameters, #headers)
post(#path, #parameters, #headers)
end
end
class DummySuper
def post(path, parameters=nil, headers=nil)
#How to verify this is called?
end
end
class Dummy < DummySuper
include ApiDoc
end
describe Dummy do
it "should call super" do
subject.expects(:enabled?).once.returns(true)
#how to expect super, the DummySuper.post ?
path = "path"
parameters = {:param1 => "someparam"}
headers = {:aheader => "someheaders"}
subject.expects(:document_request).with("post", path, parameters, headers)
subject.post(path, parameters, headers)
end
end
and the slightly modified ApiDoc.
module ApiDoc
def enabled?
ENV['API_DOC'] == "true"
end
def post(path, parameters = nil, headers = nil)
super
document_request("post", path, parameters, headers) if enabled?
end
private
def document_request(verb, path, parameters, headers)
...
end
end
I could verify the super.post in the first test, but I still can't figure out how to do just that with my Dummy class specs.

Resources