Reputation: 1
All the unit test cases should be mocked/stubbed. Rspec for checkerror method and result method.
require 'yaml'
require_relative 'checkerror'
class Operations
def initialize
@path
@checks_to_run
@check
end
# This will prints the result of each file offences or no offences
def result (result_log: File.new('result.txt', 'a+'))
# @check.errors should be stubbed with a value to enter in if or else block
if @check.errors.empty?
# Output is printing in both console as well as file
result_log.write("#{@check.checker.file_path} :: No offensenses detected\n")
puts "#{@check.checker.file_path} :: No offensenses detected\n"
else
@check.errors.uniq.each do |err|
puts "#{@check.checker.file_path} : #{err}\n"
result_log.write("#{@check.checker.file_path} : #{err}\n")
end
end
result_log.close
end
def rules_to_run
@checks_to_run = YAML.load(File.read('lib/property.yaml'))
end
def path_of_directory
@path = gets.chomp
end
def checkerror
Dir[File.join(@path, '**/*.rb')].each do |file|
@check = CheckError.new(file)
@check.check_alphabetized_constants if @checks_to_run.include?('check_alphabetized_constants')
@check.check_empty_line_before_return if @checks_to_run.include?('check_empty_line_before_return')
#result is called to print errors
result
end
end
end
I have written rspec for checkerror method
context '#checkerror' do
it 'only check the method is called or not' do
allow(@check_to_run).to receive(:include?).and_return(true)
allow(@check).to receive(:check_alphabetized_contants)
operation = Operation.new
operation.checkerror
expect(@check).to have_received(:check_alphabetized_constants)
end
end
but getting error
TypeError: no implicit conversion of nil into string.
I think haven't entered into loop of do-end block and stubbing is also syntacticly wrong I guess.
Upvotes: 0
Views: 254
Reputation: 28305
Here is a fairly minimal change to your code, so that it makes a little bit more sense and can actually be tested:
require 'yaml'
require_relative 'checkerror'
class Operations
def initialize(path: path_of_directory, checks_to_run: rules_to_run):
@path = path
@checks_to_run = checks_to_run
end
def log_result(file, errors, result_log: File.new('result.txt', 'a+'))
if errors.empty?
# Output is printing in both console as well as file
result_log.write("#{file} :: No offensenses detected\n")
puts "#{file} :: No offensenses detected\n"
else
errors.uniq.each do |err|
puts "#{file} : #{err}\n"
result_log.write("#{file} : #{err}\n")
end
end
result_log.close
end
def checkerror
Dir[File.join(@path, '**/*.rb')].each do |file|
checker = CheckError.new(file)
checker.check_alphabetized_constants if @checks_to_run.include?('check_alphabetized_constants')
checker.check_empty_line_before_return if @checks_to_run.include?('check_empty_line_before_return')
log_result(file, checker.errors)
end
end
# These methods feel very out-of-place!! It would be advisiable to move these outside of this class...
def rules_to_run
@checks_to_run = YAML.load(File.read('lib/property.yaml'))
end
def path_of_directory
@path = gets.chomp
end
end
Key notes:
@path
was nil
- so that didn't make any sense.@checks_to_run
(which you mis-spelt, by the way!) isn't a great idea. Why not just set the variable to the desired value, in the first place?@check
-- that's not how stubbing works. Stubbing isn't like "spooky action at a distance", modifying how the code actually behaves; it's about setting response behaviour of dependencies.So with that said... Here's roughly what your test could now look like:
describe '#checkerror' do
let(:path) { Dir.mktmpdir('my-temporary-directory') }
let!(:rb_file_in_path) { Tempfile.new('test-file.rb', tmpdir) }
let(:mock_checker) { instance_double(CheckError) }
it 'calls check_alphabetized_contants when this is a check to run' do
allow(CheckError).to receive(:new).and_return(mock_checker)
allow(mock_checker).to receive(:check_alphabetized_constants)
operation = Operation.new(path: path, checks_to_run: ['check_alphabetized_constants'])
operation.checkerror
expect(mock_checker).to have_received(:check_alphabetized_constants)
end
end
Upvotes: 1