Ruby rspec mocking a utility method - ruby

How does one mock a utility method that is located in a file referenced by
require 'myfile.rb'
The contents of the file are like so.
public
def my_method_name(arg1, arg2, arg3)
{
....
}
At the moment, I have something like:
double("mydouble", "my_method_name" => somehash)
I then unit test the class I am testing, which calls this method, but this does not seem to be mocking the method at all.
All help is appreciated
Basically, the method I want to mock does some network query. I want to just say: Anytime this method is called, return this hash. This method is not part of a class (or so I believe).

In Ruby all methods are associated to something (module or class). Methods that you define at the top level actually become private methods of Kernel.
x = double("mydouble", "my_method_name" => somehash)
Doesn't stub the method my_method_name. It creates a double (separate object). If you invoke #my_method_name on it, it will respond with somehash:
x.my_method_name # => somehash
Find the object the method is being invoked on. If it's easily replaced and doesn't have that much more functions, you can pass this double instead on it's place. If that is not the case, you can stub the method on that object by doing:
said_object.stub(my_method_name: somehash)
If you want to stub it for all instances of a class, you could do:
TheObjectsClass.any_instance.stub(my_method_name: somehash)
Disclaimer: The topic is a bit more complex and subject to debate. Don't consider this as a good testing practice, it just aims to help you understand how to use rspec.
You said this is related to networking. You can consider using VCR to simulate actual requests.

Since the class you are testing is the one on which this method is called, you should be stubbing the method on the same class
allow(<your_class_instance>).to receive(:my_method_name).and_return(<>)
I am assuming this method is an instance method. If its a class method, you will have to stub it at the class level

Related

How do I access objects created during the runtime of a method in rspec?

I have a class with a Klass::save method. This method will create a new instance of Klass, and then call either inst.create or inst.update depending.
I want to write an rspec test like this:
expect(instance_created_within_class_method).to receive(:create)
Can I access an object that is created during the running of the method I'm testing?
expect_any_instance_of(Class).to receive(:create) may be what you're looking for.
To call through the method you can add .and_call_original to the end of it.
Check out the RSpec documentation surrounding mocks and expectations: https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/expect-a-message-on-any-instance-of-a-class!

If "puts" method is a private instance method, why can we call it from anywhere?

I have read that "puts" is a private instance method of the module Kernel (and therefore of Object, since Object mixes in Kernel).
That's why when we call puts, we don't specify a explicit receiver. My question is, if it's a private instance method, how is it possible that we can call it from any other scope? So, we can do:
class Test
puts "hello" # self is Test. So, we are calling self.puts "hello" -
end
What am I missing here? How is it possible that this works? We are calling a private instance method?
EDIT:
Same question arises if I do this:
class Object
private
def talk
puts "hi there"
end
end
class Test
talk # outputs 'hi there'
end
Why is it possible that from class Test we can call a private method from the class Object?
Please have a look at the doc for the Kernel module - http://www.ruby-doc.org/core-2.0.0/Kernel.html.
Unlike Java, Ruby is not limited to Classes as containers of implementations. Modules act as wonderful containers which can be mixed into other classes. When a module is mixed into another class, all its instance methods become instance methods of those class. Since the Kernel module is mixed into the Object class, its methods are therefore available in all Ruby classes.
Please read the following:
Ruby access control
Common misunderstanding and clarification about access controls in Ruby
With the risk of duplication, I have to say this: private in Ruby is not the same as in C++ or Java. Subclasses of a class can call private methods declared in their superclass. In fact, you can call private method of any class using :send. The only difference between private and protected methods is that private methods can't be called with explicit receivers.
Even the last rule has an exception. If your private method is something like age=, it can (and has to be) called with self. Funny, isn't it? :)
UPDATE: (to explain the gist):
The talk method which you wrote in your code above is being called on the main object which is the context for all Ruby programs. It's not being called on the Test class which is why it's not working for your second gist.
In the gist that I have provided, talk is a private class method which is why it gets executed at the time of class definition. In the same gist, the talk2 method is an instance method and can only be called from within instance methods. Your example gist didn't work because you were trying to invoke an instance method at the time of defining the class.
I don't understand why such long answer as in the other answer is required, or is upvoted. The answer to your question is simple.
It is because almost all classes (i.e., anything other than BasicObject) includes Kernel. Therefore, in the scope of a usual object, Kernel class is inherited, and hence its methods are accessible. That is all.

Does ruby call initialize method automatically?

Do I need to explicitly initialize an object if an initialize method is included in class definition?
No, Ruby does not call initialize automatically.
The default implementation of Class#new looks a bit like this:
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
obj
end
end
[Actually, initialize is private by default so you need to use obj.send(:initialize, *args, &block).]
So, the default implementation of Class#new does call initialize, but it would be perfectly possible (albeit extremely stupid) to override or overwrite it with an implementation that does not.
So, it's not Ruby that calls initialize, it's Class#new. You may think that's splitting hairs, because Class#new is an integral part of Ruby, but the important thing here is: it's not some kind of language magic. It's a method like any other, and like any other method it can be overridden or overwritten to do something completely different.
And, of course, if you don't use new to create an object but instead do it manually with allocate, then initialize wouldn't be called either.
There are some cases where objects are created without calling initialize. E.g. when duping or cloneing, initialize_dup and initialize_clone are called instead of initialize (both of which, in turn, call initialize_copy). And when deserializing an object via, say, Marshal, its internal state is reconstructed directly (i.e. the instance variables are set reflectively) instead of through initialize.
Yes, it's called from new method, which you use to create objects.
It depends on your definition of "explicit". Usually you need to, even if there are no arguments:
object = MyClass.new(...)
In some cases there are factory methods that produce instances you can use, creating a form of implicit initialization:
object = MyClass.factory_method(...)
This would have the effect of calling MyObject.new internally.
There are some libraries which have rather unusual method signatures, like:
object = MyClass(...)
object = MyClass[...]
The effect is the same, as these might look odd but are just method calls.

How to test private functions in a module

I have a two part question:
Part 1
I have a module that has a public class method which depends on a few private helper methods in the module. What is the best way to test these private helper methods? They contain complex logic that needs to be tested, but they should not be exposed to be called as they alone provide nothing useful.
I read on this stackoverflow post that the convention is to do:
module GTranslate
class Translator
def perform( text ); 'hola munda'; end
end
def self.translate( text )
t = Translator.new
t.perform( text )
end
end
and then write tests on the public methods of class GTranslate::Translator. However, I do not want this class to be able to instantiate or have the methods on them called.
Part 2
Seeing that the public method on a module is defined as self.someMethodName, does this mean the helper methods have to be defined as self.helperName?
There will be no instance of a module (if you can even create instances of modules (I'm new to Ruby)) so I can't use the send method defined on an instance to invoke the method from my tests?
Any ideas?
There is some bit of debate about testing private methods as you will see in other answers. Before you test them you should consider whether it is the best choice. David Brady has a great podcall with Robert C. (Uncle Bob) Martin where they discuss this issue and some of the possible solutions including testing through the public interface, and refactoring into a separate class.
That being said, this is Ruby. If you want to test private methods use instance_eval (or class_eval for class methods) to run your test in the context of the module.
edit: After some quick IRB work modules take a little more work
Given:
module Foo
class << self
private
def bar
...
end
end
end
To test Foo.bar put in your test file:
Module Foo
class << self
puiblic :bar
end
end
For the duration of your tests bar will be public and visible.
end edit
See also:
Yes You Should Test Private Methods (Sometimes)
Test Everything, But Not Private Methods
MORE Testing Private Method
I would say you have three options.
Find a way to test the functionality using the class's public methods. All the class functionality should generally be exposed by its public methods. If you can't test a class just by using its public methods, this may indicate a deeper problem with the design.
If option 1 doesn't work (and indeed sometimes it doesn't), refactor the private functionality out to a separate class, in which these methods are public. This seems to be what you're suggesting, and I don't see a problem with that. Testing is an integral part of the system you're building and should be treated as such. Making functionality public "just for testing" is completely valid in my opinion.
Make the functions public and test them. This is technically easiest but is less clean than option 2.
There are two cases:
The private method gets called by a public method, or by a private method that gets called by a public method, or by a private method that gets called by a private method that gets called by a public method, or … (you get the idea). In that case, you don't need to test the private method, because it is already tested through the public method.
The private method never gets called by a public method. In that case, you don't need to test it either, you can simply delete it because it never gets called.
So, in both cases you simply don't need to test it in the first place.
(Note that it's a little bit more complicated than that, since the private method might be called via reflection or other means. But the gist is: either someone somewhere calls the private method, in which case it is tested through that someone, or noone calls the private method, in which case it is dead code.)
If I may make a small advertisement for Test-Driven Development: in TDD, it is actually impossible for untested private methods to exist. The only way for a private method to be introduced into the system, is by extraction from an already tested public method. (Actually, in TDD, it is impossible for any untested code to exist, so the statement that it is impossible for untested private methods to exist is trivially true.)
In general, private methods usually are created by extracting them from a public method that has become too big or too complex. The nice thing about this is that the Extract Method Refactoring has a very convenient property: like all other Refactorings, it doesn't change the externally observable behavior, but unlike many other Refactorings, which entail rather significant changes to the internal logic (e.g. the Null Object Refactoring or the Replace Conditional With Polymorphism Refactoring), it does not change the internal logic, either. It just shuffles code around. (In fact, with a good optimizing compiler like the one in Rubinius, IronRuby or JRuby, the calls to the private methods will probably be inlined, so that the code that gets actually executed is 100% the same both before and after extracting the methods.)
So, if your code was tested before you moved into a private method, then it is guaranteed to still be tested after you move it.

method_missing in "Programming Ruby" over my head

method_missing
*obj.method_missing( symbol h , args i ) → other_obj
Invoked by Ruby when obj is sent a
message it cannot handle. symbol is
the symbol for the method called, and
args are any arguments that were
passed to it. The example below
creates a class Roman, which responds
to methods with names consisting of
roman numerals, returning the
corresponding integer values. A more
typical use of method_missing is to
implement proxies, delegators, and
forwarders.
class Roman
def roman_to_int(str)
# ...
end
def method_missing(method_id)
str = method_id.id2name
roman_to_int(str)
end
end
r = Roman.new
r.iv ! 4
r.xxiii ! 23
r.mm ! 2000
I just heard about method-missing and went to find out more in Programming Ruby but the above explanation quoted from the book is over my head. Does anyone have an easier explanation? More specifically, is method-missing only used by the interpreter or is there ever a need to call it directly in a program (assuming I'm just writing web apps, as opposed to writing code for NASA)?
It's probably best to not think of ruby as having methods. When you call a ruby "method" you are actually sending a message to that instance (or class) and if you have defined a handler for the message, it is used to process and return a value.
So method_missing is a special definition that gets called whenever ruby cannot find an apropriate handler. You could also think of it like a * method.
Ruby doesn't have any type enforcement, and likewise doesn't do any checking as to what methods an object has when the script is first parsed, because this can be dynamically changed as the application runs.
What method_missing does, is let you intercept and handle calls to methods that don't exist for a given object. This provides the under-the-hood power behind pretty much every DSL (domain-specific language) written in Ruby.
In the case of the example, every one of 'r.iv', 'r.mm', and so on is actually a method call to the Roman object. Of course, it doesn't have an 'iv' or an 'mm' method, so instead control is passed to method_missing, which gets the name of the method that was called, as well as whatever arguments were passed.
method_missing then converts the method name from a symbol to a string, and parses it as a Roman number, returning the output as an integer.
It's basically a catch-all for messages that don't match up to any methods. It's used extensively in active record for dynamic finders. It's what lets you write something like this:
SomeModel.find_by_name_and_number(a_name, a_number)
The Model doesn't contain code for that find_by, so method_missing is called which looks at is says - I recognize that format, and carries it out. If it doesn't, then you get a method not found error.
In the Roman example you provide it illustrates how you can extend the functionality of a class without explicitly defining methods.
r.iv is not a method so method_missing catches it and calls roman_to_int on the method id "iv"
It's also useful when you want to handle unrecognized methods elsewhere, like proxies, delegators, and forwarders, as the documentation states.
You do not call "method_missing" (the interpreter calls it). Rather, you define it (override it) for a class which you want to make to be more flexible. As mentioned in other comments, the interpreter will call your version of method_missing when the class (or instance) does not ("explicitly"?) define the requested method. This gives you a chance to make something up, based on the ersatz method/message name.
Have you ever done any "reflection" programming in Java? Using this method would be as if the class to be accessed via reflection could look at the string (excuse me, "symbol") of the method name if a no-such-method exception was thrown, and then make something up as that method's implementation on the fly.
Dynamic programming is kind of a "one-up" on reflection.
Since you mention web apps I'll guess that you are familiar with Ruby on Rails. A good example of how method_missing can be used is the different find_by_<whatever> methods that's available. None of those methods actually exist! They are synthesized during run time. All of this magic happens because of how ruby intercepts invocations of non-existing methods.
You can read more about that and other uses of method_missing here.
ActiveRecord uses method_missing to define find_by methods. But since, method_missing is basically a last resort method, this can be a serious performance bottleneck. What I discovered is that ActiveRecord does some further awesome metaprogramming by defining the new finder method as a class method !! Thus, any further calls to the same finder method would not hit the method_missing because it is now a class method. For details about the actual code snippet from base.rb, click here.

Resources