How to Assert Certain Method Is Called with Ruby Minitest Framework

How to assert certain method is called with Ruby minitest framework?

With minitest you use expect method to set the expectation for a method to be called on a mock object like so

obj = MiniTest::Mock.new
obj.expect :right

If you want to set expectation with parameters and return values then:

obj.expect :right, return_value, parameters

And for the concrete object like so:

obj = SomeClass.new
assert_send([obj, :right, *parameters])

Ruby - Testing a method that calls itself in Minitest

I'm not very familiar with minitest, but I expect you need to wrap the raise(exception) in a block, otherwise your test code is raising the exception immediately in your test (not as a result of the stubbed method being called).

Something like:

class CustomTestError < RuntimeError; end
def test_playRound_a_input_triggers_getPlayerSet
raise_error = -> { raise(CustomTestError) }
@game.stub(:getPlayerSet, raise_error) do
assert_raises(CustomTestError) do
simulate_stdin("") {
@game.playRound
}
end
end
end

-- EDIT --

Sometimes when i'm having difficulty testing a method it's a sign that I should refactor things to be easier to test (and thus have a cleaner, simpler interface, possibly be easier to understand later).

I don't code games and don't know what's typical for a game loop, but that method looks very difficult to test. I'd try to break it into a couple steps where each step/command can be easily tested in isolation. One option for this would be to define a method for each command and use send. This would allow you to test that each command works separately from your input parsing and separately from the game loop itself.

  COMMANDS = {
q: :quit,
# etc..
}.stringify_keys.freeze

def play_round # Ruby methods should be snake_case rather than camelCase
@board.print_board
run_command(gets.chomp)
play_round unless @quitted || @board.board_complete
end

def run_command(input)
command = parse_input_to_command(input)
run_command(command)
end

def parse_input_to_command(input)
COMMANDS[input] || :bad_command
end
def run_command(command)
send("run_#{command}")
end
# Then a method for each command, e.g.
def run_bad_input
puts "Input not recognized"
end

However, for this type of problem I really like a functional approach, where each command is just a stateless function that you pass state into and get new state back. These could either mutate their input state (eww) or return a new copy of the board with updated state (yay!). Something like:

  COMMANDS = {
# All state change must be done on board. To be a functional pattern, you should not mutate the board but return a new one. For this I invent a `.copy()` method that takes attributes to update as input.
q: -> {|board| board.copy(quitted: true) },
h: -> HintGiver.new, # If these commands were complex, they could live in a separate class entirely.
bad_command: -> {|board| puts "Unrecognized command"; board },
#
}.stringify_keys.freeze
def play_round
@board.print_board
command = parse_input_to_command(gets.chomp)
@board = command.call(@board)
play_round unless @board.quitted || @board.board_complete
end

def parse_input_to_command(input)
COMMANDS[input] || COMMANDS[:bad_command]
end

Stubbing a method of tested class with Minitest

I think if I understand correctly you are looking for MiniTest::Object#stub

def test_bar
a = A.new
# use stubbed_foo in a instead of foo
a.stub :foo, 5 do
result = a.bar
# some assert
end
end

Here is a full example:

require 'minitest/autorun'

class A
def bar
foo + 1
end
def foo
3
end
end

class TestA < MiniTest::Unit::TestCase

def test_bar
a = A.new
a.stub :foo, 5 do
result = a.bar
assert_equal(6,result)
end
end

def test_actual_bar
a = A.new
result = a.bar
assert_equal(4,result)
end
end

Update: Based on Comment how to return multiple values

class A 
def bar
foo + 1
end
def foo
3
end
end

class TestA < MiniTest::Unit::TestCase

def test_bar
a = A.new
stubbed_foo = [5,7].to_enum
a.stub :foo, ->{stubbed_foo.next} do
assert_equal(6,a.bar)
assert_equal(8,a.bar)
end
end

def test_actual_bar
a = A.new
assert_equal(4,a.bar)
end
end

How minitest testing framework works in rails?

check if name, type parameter exist when creating a new object of Post
class. How can I do it post_test class?

Is this test method are checking the presence of name in post?

Sort of. The assertion checks that saving the new Post instance fails, but there are several reasons for that result - e.g. missing :name and :type attributes, the before_create filter that could hijack the save operation.

If you want to test each of these validations individually, you'll want to start with a known valid Post record and manipulate it to trigger each validation to fail. Usually, I'll have at least one minimally valid record set up in my fixture file - in this case, I'll call it :mvp. Ex:

test 'MVP is valid' do
assert posts(:mvp).valid?, 'Minimum valid Post is invalid'
end

test 'should not save simulations without name' do
post = posts(:mvp)
post.name = nil
assert post.invalid?, 'Post is valid without a name'
end

...

For the most part, I find that testing simple validations (presence, simple numericality, etc.) clutters my tests and smells a little like testing the framework instead of my own application code, so I'll often skip them.

How can I test check_Validation through PostTest class?

check_validation is marked as a private method, and in general, you don't want to directly test private methods. You can, however, verify that the conditions you set on newly created models match your expectations:

test 'newly created Post has settings XYZ' do
post = Post.new(...)
assert post.save, 'Post could not be saved'
# assertions to test #check_validations side effects here...
end

You don't include the body of your check_validation method, so I don't know what you've got in mind here. With a name like that though, I'm inclined to believe you're trying to do some kind of validation that would be better left to a custom validation method defined using the validate method. See the docs to see whether it applies in your case.

How to check throw error if posts is not belong to users?

I'd make this a validated condition on your Post class as:

class Post
belongs_to :user
validates :user, presence: true
end

Hope that helps somewhat. I've tried to answer your questions in a way that will let you get on with your work, but if you're interested in learning to be productive with Rails and Minitest, you're going to want to do a deeper study of the framework and how it's used with Rails.

Rspec method similar to MiniTest 'assert'

Rspec uses expect() in a similar way to Minitest's assert. expect(actual).to eq(expected) You can get in depth with the docs at https://www.relishapp.com/rspec/ . Note that there are few different ways to test the truth in Rspec(from https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers):

expect($b.link(:text => 'DAM').present?).to be true      # passes if actual == true
expect($b.link(:text => 'DAM').present?).to eq true # passes if actual == true
expect($b.link(:text => 'DAM').present?).to be_truthy # passes if actual is truthy (not nil or false)

If you spend a lot of time in rspec, you can also create custom matchers for common tests that extend the use of "be" e.g.

RSpec::Matchers.define :be_present do
match do |actual|
actual.present?
end
end

expect($b.link(:text => 'DAM')).to be_present # passes if $b.link(:text => 'DAM').present? == true

Ruby: Mocking a class method with MiniTest?

This might not be helpful to you if you're stuck using 2.12.1, but looks like they added method stubbing to minitest/mock in HEAD here.

So, were you to update to minitest HEAD, I think you could do this:

product = Product.new
Product.stub(:find, product) do
assert_equal product, Product.find(1)
end


Related Topics



Leave a reply



Submit