I am calling a scalar valued function but having hard time trying to figure out how can i create mock test cases for it.
I just want to create some mock test cases like,
function returns successfully one value
function returns conversion error
I tried something below but here i have to call the actual function, which i dont want to because if database changes it'll cause the test case fail hence want to mock cases.
require 'rails_helper'
describe ScalarSqlFunction::Base do
describe '#exec' do
let!(:success) { 0 }
context 'with valid input' do
let(:response) {
ScalarSqlFunction::CalcTotal(105)
}
before do
allow(response)
.to receive(return_code).and_return(success)
end
it 'returns success' do
expect(response.return_code).to eq(success)
end
end
end
end
You can create a mock object for ScalarSqlFunction::CalcTotal
require 'rails_helper'
describe ScalarSqlFunction::Base do
describe '#exec' do
let!(:success) { 0 }
context 'with valid input' do
let(:response) { double('Response') }
before do
allow(response)
.to receive(return_code).and_return(success)
end
it 'returns success' do
expect(response.return_code).to eq(success)
end
end
end
end
Related
I am a very new coder and trying to write rspec for a class that test the conditional statement/logic. I started sudo coding for it but I was told to make mock STDIN which I don't know how to. Can someone please write the rspec for the class or give me a few idea how to create a mock STDIN. I need help writing rspec for the conditional statement/logic, if some can please just write the test for one of the context then I can do rest based on that.
require 'rails_helper'
module BAB::ACA
RSpec.describe partfinder do
describe '#find_part_id' do
let(:face) { create(:face) }
subject { described_class.find_part_id(face) }
context 'When bab con already exists' do
context 'when there are more than one part ids' do
#create part ids
context 'when user input matches an existing id' do
#mock STDIN that matches an existing, subject should equal that id
end
context 'when user input does not match an existing id' do
# mock STDIN that does match existing id, should return failure message
end
end
context 'when there is only one bab part id' do
# subject should equal the one that already exists
end
end
context 'when av con does not yet exist' do
# mock STDIN and make sure subject equals what you mocked
end
end
end
module BAB::ACA
class partfinder
def self.find_part_id(face)
av_con = BAB::Child:Fail.find_by(
face: face
reg: BAB:Child.find_reg
)
if av_con
look_id(face, av_con)
end
else
puts "What is #{face.name} BAB part id? must be 6"
STDIN.gets.chomp
end
end
def self.look_id(face, av_con)
if av_con.part_ids.length > 1
ask_for_id(face, av_con)
else
av.con.part_ids.first
end
end
def self.ask_for_id(face, av_con)
puts "What is #{face.name} BAB part id? "
bab_part_id = STDIN.gets.chomp
unless av.con.part_ids.include?(bab_part_id)
fail 'Entered id doesn't match'
end
bab_part_id
end
end
end
You can use method stubs.
In this case you want to stub STDIN.gets.chomp, so you'd do something like this:
describe '#find_part_id' do
before do
allow(STDIN.gets).to receive(:chomp).and_return(stdin_input)
end
let(:stdin_input) { 'user input from stdin' }
let(:face) { create(:face) }
subject { described_class.find_part_id(face) }
context 'When bab con already exists' do
context 'when there are more than one part ids' do
it 'some test' do
# your test here
end
end
# more contexts...
context 'a context that needs a different stdin_input' do
let(:stdin_input) { 'some different user input from stdin' }
it 'another test' do
# your test here
end
end
end
end
Where stdin_input is the string you want the user to enter for your tests.
I'm using custom assertions in my minitests and I want to unit test my assertions. Of course I can test the happy path but I want to assert that a test actually fails.
module Minitest
module Assertions
def assert_exists(value, msg = nil)
assert(!value.to_s.empty?, msg)
end
end
end
In my test I want to write something like
describe 'Assertions' do
it 'is empty' do
assert_raises assert_exists('')
end
end
Is there a way to do this?
Something like this? (You need to specify the exception you are expecting, and pass the call as a block):
describe 'Assertions' do
it 'is empty' do
assert_raises(Minitest::Assertion) do
assert_exists('')
end
end
end
This will include the call to assert in your assert_raises in the summary, which may not be exactly what you expect, but otherwise works.
My weakest point when it comes to coding, is using TDD & BDD methods - I tend to just write code.. but it is something that I am trying to work on.
Could anyone point out the best way to go about the following problem:
Class1:
module TempMod
class MyClass
def initalize(config)
#config = config
end
def process(xml)
if react_upon? xml.something
puts 'yeah'
else
puts 'nah'
end
end
def react_upon?(xml_code)
#code here
end
end
end
So lets say I wanted to test this class, or build it from a TDD point of view so I write my tests:
describe TempMod::MyClass do
let(:config) {double}
let(:myclass) {TempMod::MyClass.new config}
context 'Given that the xml is something we react upon' do
it 'should check that it is valid' do
myclass.process '<some><xml>here</xml></some>'
end
it 'should output yea'
end
end
How do I test that it is calling the react_upon? method. Do I even want to see it is calling it?
Is the proper way to test it, to test all the functions like the react_upon? itself independently of the other functions?
This is properly the main thing that is most confusing me with this sort of testing. Am I testing the whole class, or just individually testing the functions, and not their interactions with the other functions in that class?
Also I realize the the react_upon? might not adhere to the Single responsibility principle and I would probably move that out to its own module/class which I could test using a stub.
If anyone can shed some light on this for me that would be awesome.
edit:
describe TempMod::MyClass do
let (:valid_planning_status_xml) {
'<StatusUpdate> <TitleId>2329</TitleId> <FromStatus>Proposed</FromStatus> <ToStatus>Confirmed</ToStatus> </StatusUpdate>'
}
let(:config) { double }
let(:status_resolver) { double }
subject(:message_processor) { TempMod::MyClass.new config, status_resolver }
context 'Given that the message XML is valid' do
it 'should check the context of the message' do
expect(message_processor.process valid_planning_status_xml).to call :check_me
end
context 'Given that the message is for a planning event update' do
it 'should call something' do
pending
end
end
context 'Given that the message is for a recording job update' do
end
context 'Given that the message is for a video title update' do
end
end
end
Your question confused me a bit is this what you are asking
module TempMod
class MyClass
def initalize(config)
#config = config
end
def process(xml)
react_upon?(xml.something) ? 'yeah' : 'nah'
end
def react_upon?(xml_code)
#code here
end
end
end
Then test like
describe TempMod::MyClass do
let(:config) {double}
let(:myclass) {TempMod::MyClass.new config}
context 'Given that the xml is something we react upon' do
it "should respond to react_upon?" do
expect(myclass).to respond_to(:react_upon?)
end
it "should react_upon? valid xml" do
expect(myclass.react_upon?(YOUR VALID REACTION GOES HERE)).to be_true
end
it "should not react_upon? invalid xml" do
expect(myclass.react_upon?(YOUR INVALID REACTION GOES HERE)).to be_false
end
it "should say 'yeah' if it is valid" do
expect(myclass.process('<some><xml>here</xml></some>')).to eq('yeah')
end
it "should say 'nah' if it is invalid" do
expect(myclass.process('<some><xml>here</some>')).to eq('nah')
end
it 'should check the context of the message' do
expect(myclass).to receive(:react_upon?).with('<some><xml>here</xml></some>')
myclass.process('<some><xml>here</xml></some>')
end
end
end
Right now your tests have no expectations so I added one that expects myclass to respiond_to the react_upon? method and another that expects myclass.process(xml) to respond with a String that equals yeah.
How do I unit test the following:
def update_config
store = YAML::Store.new('config.yaml')
store.transaction do
store['A'] = 'a'
end
end
Here is my start:
def test_yaml_store
mock_store = flexmock('store')
mock_store
.should_receive(:transaction)
.once
flexmock(YAML::Store).should_receive(:new).returns(mock_store)
update_config()
end
How do I test what is inside the block?
UPDATED
I have converted my test to spec and switched to rr mocking framework:
describe 'update_config' do
it 'calls transaction' do
stub(YAML::Store).new do |store|
mock(store).transaction
end
update_config
end
end
This will test the transaction was called. How do I test inside the block: store['A'] = 'a'?
First, you can write this a little simpler -- your test using RR isn't a direct port of your test using FlexMock. Second, you're not testing what happens within the block at all so your test is incomplete. Try this instead:
describe '#update_config' do
it 'makes a YAML::Store and stores A in it within a transaction' do
mock_store = {}
mock(mock_store).transaction.yields
mock(YAML::Store).new { mock_store }
update_config
expect(mock_store['A']).to eq 'a'
end
end
Note that since you're providing the implementation of #transaction, not merely the return value, you could have also said it this way:
describe '#update_config' do
it 'makes a YAML::Store and stores A in it within a transaction' do
mock_store = {}
mock(mock_store).transaction { |&block| block.call }
mock(YAML::Store).new { mock_store }
update_config
expect(mock_store['A']).to eq 'a'
end
end
You want to call yields:
describe 'update_config' do
it 'calls transaction which stores A = a' do
stub(YAML::Store).new do |store|
mock(store).transaction.yields
mock(store).[]=('A', 'a')
end
update_config
end
end
Check out this answer for a different approach to a related question. Hopefully the rr api documentation will improve.
So I'm fairly new to ruby in general, and I'm writing some rspec test cases for an object I am creating. Lots of the test cases are fairly basic and I just want to ensure that values are being populated and returned properly. I'm wondering if there is a way for me to do this with a looping construct. Instead of having to have an assertEquals for each of the methods I want to test.
For instace:
describe item, "Testing the Item" do
it "will have a null value to start" do
item = Item.new
# Here I could do the item.name.should be_nil
# then I could do item.category.should be_nil
end
end
But I want some way to use an array to determine all of the properties to check. So I could do something like
propertyArray.each do |property|
item.#{property}.should be_nil
end
Will this or something like it work? Thanks for any help / suggestions.
object.send(:method_name) or object.send("method_name") will work.
So in your case
propertyArray.each do |property|
item.send(property).should be_nil
end
should do what you want.
If you do
propertyArray.each do |property|
item.send(property).should be_nil
end
within a single spec example and if your spec fails then it will be hard to debug which attribute is not nil or what has failed. A better way to do this is to create a separate spec example for each attribute like
describe item, "Testing the Item" do
before(:each) do
#item = Item.new
end
propertyArray.each do |property|
it "should have a null value for #{property} to start" do
#item.send(property).should be_nil
end
end
end
This will run your spec as a different spec example for each property and if it fails then you will know what has failed. This also follows the rule of one assertion per test/spec example.
A couple points about Object#send()...
You can specify parameters for the method call too...
an_object.send(:a_method, 'A param', 'Another param')
I like to use this other form __send__ because "send" is so common...
an_object.__send__(:a_method)