Mocking complex query with several objects - spring

How should I go about mocking this query, so that I receive a pre-defined ArrayList<Follow>?
I've tried a number of ways but they've all been clunky and... don't work because I don't know how to deal with add().
result = (ArrayList<Follow>) session.createCriteria(Follow.class).add(Restrictions.eq("followerUsername", followerUsername)).list();

I would personally extract the code into another method and then just mock that method.
It would look like:
ArrayList<Follow> getFollowListByUsername(String followerUsername) {
return (ArrayList<Follow>) session.createCriteria(Follow.class).add(Restrictions.eq("followerUsername", followerUsername)).list()
}
Then all you need to do is mock the getFollowListByUsername method which is extremely easy.

Related

How to mock mongodb in rspec (beginner)

I am an old programmer, but new to ruby, and thrown into an existing code base where I need to extend an rspec test.
The code that needs to be tested uses MongoDB (mongoid), and has a pattern similar to this:
objects = Database::MyTable.active.where(object_id: object_id).to_a
I want my rspec code to provide the objects hard-coded in the test. How can I do that?
Because of the "chain" of methods, stubbing is a little awkward, but it can be done.
allow(Database::MyTable).to(
receive(:active).and_return(double(
where: [{ id: 1 }, { id: 2 }]
))
)
We have stubbed active to return a mock (a double) on which we stub where.
Docs: rspec-mocks
PS: There are many other ways to write these stubs, some objectively better, some subjectively better. There are also ways to refactor your code to make stubbing easier.
PPS: Welcome to ruby!
I would separate the code that retrieves the data (including the line you mentioned) into one method and the code that consumes/operates on the data into another method, then mock the entire retrieval method. This way you don't need to muck with the exact queries used.

Why is there two identical method in laravel message bag?

I was reading laravel documentation regarding messagebag. There I found any() and isNotEmpty() methods. Both of them does the exact same thing. They try to determine if there are any messages and return true if there are any. I went to see the source code and I found that isNotEmpty() is doing nothing but calling the any() method.
public function isNotEmpty()
{
return $this->any();
}
public function any()
{
return $this->count() > 0;
}
What I don't understand is why laravel does same things in two places? Shouldn't one method be sufficient for this job?
You are right that one of the two methods would be sufficient. There is also not a single reason both of these methods exist, but I guess the combination of the following (and possibly even more) is why we have them:
The any() method has been there long before isNotEmpty() and there has always been an isEmpty() method alongside any() (as inverse method).
Because isNotEmpty() is a more obvious method name than any(), it has been added some years ago.
For backwards compatibility and because the implementation of any() is really trivial, there has never been a good reason to remove any().
It is actually quite common for programming languages and libraries to have different methods for the same thing. Some languages are using it more often and more obvious than others, but I guess it has a lot to do with readability. Although isNotEmpty() as in if ($messages->isNotEmpty()) { ... } is a lot longer than if ($messages->any()) { ... }, it seems more readable and understandable to me. But not everyone sees it the same way and my best guess is that there is a fan of any() in the group of the framework maintainers who doesn't want to write more than necessary.

How to unit test a class that depends heavily on other classes?

My understanding is that unit testing should test classes in isolation, focusing on granular behavior and substituting objects of other classes using doubles/mocks wherever possible. (Please correct me if I'm wrong here.)
I'm writing a gem with a class called MatchList. MatchList::new takes two arguments, each an instance of another class called MatchPhrase. MatchPhrase contains some behavior that MatchList depends heavily on (i.e., if you feed anything other than a MatchPhrase to MatchList::new, you're going to get a bunch of "undefined method" errors).
My current (naive?) test setup uses let statements to assign variables for use in my examples:
let(:query) { MatchPhrase.new('Good Eats') }
let(:candidate) { MatchPhrase.new('Good Grief') }
let(:match_list) { MatchList.new(query, candidate) }
How do I write this unit test? Am I right in thinking it should be done without invoking the MatchPhrase class? Is that even possible?
For reference, here is what the MatchList class looks like:
class MatchList < Array
attr_reader :query, :this_phrase, :that_phrase
def initialize(query, candidate)
super(query.length)
#query = query
#this_phrase = query.dup
#that_phrase = candidate
find_matches until none?(&:nil?)
end
private
def find_matches
query.each.with_index do |this_token, i|
next unless self[i].nil?
that_token = this_token.best_match_in(that_phrase)
next if that_token.match?(that_token) &&
this_token != that_token.best_match_in(this_phrase)
self[i] = this_token.match?(that_token) ? that_token : NilToken.new
this_phrase.delete_once(this_token)
that_phrase.delete_once(that_token)
end
end
end
My understanding is that unit testing should test classes in isolation, focusing on granular behavior and substituting objects of other classes using doubles/mocks wherever possible. (Please correct me if I'm wrong here.)
In my understanding this is not true.
Using doubles/mocks has advantages and disadvantages.
Advantage is that you can take a slow service like database, email and mock it with fast performing object.
Disadvantage is that object that you are mocking is not "real" object and might surprise you and behave differently than real object would.
That's why it's always better to use real objects if practical.
Only use mocks if you want to speed up your tests or if it leads to much simpler tests. Even then have one test using real object to verify that it all works. This is called integration test.
Considering your case:
let(:query) { MatchPhrase.new('Good Eats') }
let(:candidate) { MatchPhrase.new('Good Grief') }
let(:match_list) { MatchList.new(query, candidate) }
There is really no advantage to mock query or candidate.
Mocking should be done for legitimate reasons and not as a matter of principle.
If there is only one collaborator class and your primary class is heavily coupled to it, mocking out the collaborator as a matter of principle may result in more fragility than benefit as the mock will not reflect the behavior of the collaborator.
Mocks and stubs are good candidates when you can reason against the mock's interface instead of an implementation. Let's ignore the existing code and look at the interfaces in use here:
MatchList.new takes a query and candidate
query is an Enumerable containing objects which implements best_match_in?(something)
The objects in query also implement delete_once(something)
candidate also implements delete_once(something)
best_match_in? returns something that implements match? and best_match_in?
Looking at the interfaces in use, MatchList appears to rely pretty heavily on the implementation of the query and candidate objects. Smells like a case of feature envy to me. Perhaps this functionality should reside within MatchPhrase instead.
In this case, I would write unit tests using actual MatchPhrase objects with a note to refactor this code.
Your understanding of using test part is correct. Its about focusing on granular behavior. E.g individual methods.
However to test the individual methods, try using doubles/mocks is not advisable. Marko ^^ has outlined the advantages / disadvantages of the mocks. I personally prefer not to not to use doubles/mocks as much as I can.
Its always a balance between the speed of your tests and the objects you create.
Before moving to doubles/mocks, its a good idea to see if you can write your test without saving the values to the DB. Like you have done before. That is faster than saving and retrieving the values from the DB.
One more thing is, private methods and not generally unit tested. This is with understanding of, the caller of your private method will have a unit test.
let(:query) { MatchPhrase.new('Good Eats') }
let(:candidate) { MatchPhrase.new('Good Grief') }
it 'check your expectation' do
expect(MatchList.new(query, candidate).query).to <check the expectation>
end
However I will re-evaluate the following points.
1 - do u want to call find_matches from initializer
2 - Let find_matches to return a value and then assign it to the #query variable (so that its easy to test the method with a return value)
3 - rename the query param in init to something else (just to avoid the confusion)
And the golden rule is If its hard to test (specially unit test), maybe your are doing something wrong.
HTH

Using Ruby's Struct to stub an object for minitest

This is working but it feels sloppy to me. I'm wondering if it is a code smell or if there is a better way to be accomplishing this result. Basic question is how to stub some arbitrary object in ruby.
I'm testing an edge case- that the final value of a parsing helper method correctly formats the result of a google analytics query (thus the odd assert statement) the incoming data is a google analytics object whose data is inside- essentially we have to call result.data["rows"]. The whole purpose of the struct here is to give my method's internals the ability to send that #data message. The test passes/fails appropriately but like I said, i'm wondering if this was the best way to go about it, for example getting my data out of the GA result object before sending it to be parsed.
my approach from the test- effectively it calls parse_monthly_chart_data(#ga_result)
def test_parse_monthly_chart_data_with_good_values
typical_data = {"rows" => [["0000", "194346"]...more arrays...]}
typical_vals = typical_data["rows"].to_h.values.map(&:to_i)
expected_result = typical_vals[-30..-1].inject(&:+)
Struct.new("GaResult") {def data; end }
#ga_result = Struct::GaResult.new
#ga_result.stub :data, typical_data do
assert_equal(ga.send(:parse_monthly_chart_data, #ga_result).flatten.last, expected_result)
end
end
Edit: I've solved for part of this issue by replacing stub with mocha's implementation. I'm still wondering if this is a code smell.
Not at all. I use this type of thing all the time. What you're using is called stubbing and using a Struct to accomplish this is no different than using a testing framework's implementation of a stub.
For further reading on mocks, stubbing, faking, etc. see this SO Question.

is it possible to tell rspec to warn me if a stub returns a different type of object than the method it's replacing?

I have a method called save_title:
def save_title (data)
...
[ if the record exists, update, return 0]
[ if the record is new, create, return 1]
end
All fine, until I stubbed it:
saved_rows = []
proc.stub(:save_title) do |arg|
saved_rows << arg
end
The bug here is that I was using the integer returned from the real method to determine how many records were created vs. updated. The stub doesn't return an integer. Oooops. So the code worked fine in reality, but appeared broken in the test. A while later (more than I care to admit, cursing included) I realize the stub and the real method don't behave the same. Such are the pitfalls of dynamic languages I suppose.
Questions:
Can I tell rspec to warn me if the stub doesn't return the same sort of thing as the real method?
Is there an analyzer gem that I can use to warn about this sort of thing?
Is there some sort of best practice that I don't know about with returning values from methods?
1) There is no way that rspec can know what type of object the method is supposed to return, that's for you to tell it, however...
2) There is something you can look into. Instead of using a stub, try using a mock instead as your test double. It is basically the same thing as a stub, however, you can do many more validations on it (check out the documentation here). Things like how many times the specific method was called, the arguments it should be called with and what the return value should be as well. Your test will fail if any of those validations don't pass.
3) The best practice would be the method name itself. For example, methods ending in ? like object.exists? should always return a boolean value. In your case, I would suggest a refactoring of your method, maybe divide it in two, one for updating and one for creating and have another method to tell you if an object exists or not. It is not good practice to have a method behave in two different ways depending on the input (see separation of concerns)
Good luck! hope this helps.

Resources