Tigiras
Tigiras

Reputation: 57

Testing method that needs to sort hash by value in RSpec

I am trying to test my method that takes a hash and re-orders it. I currently have:

def sort_views 
    help = view_counter.sort_by { |route, length| length }.reverse.to_h
    p help         #just so I can see the output in the test
  end

Then for my test I have:

describe "#sort_views" do
    let(:result) do {
      "/help_page/1" => 3,
      "/about/2" => 1,
      "/contact" => 1,
      "/home" => 1,
      "/index" => 2,
    }     end
    it "then sorts them via the view count" do
      expect(subject.sort_views).to be(result)
    end
  end

My issue is that the test passes.... However, I purposely have the order wrong at the moment in the result. Yet the p help in the method CORRECTLY re-orders it, so the output is actually different. I have tried eq and eql but I believe they just test structure? I know be and equal won't work...

For context my p help outputs: {"/help_page/1"=>3, "/index"=>2, "/about/2"=>1, "/home"=>1, "/contact"=>1} when the test is run.

So is there a way for me to say test the order of the result hash in my test too without calling .sort_by { |route, length| length }.reverse.to_h on my result variable as well??

Upvotes: 1

Views: 463

Answers (1)

akerr
akerr

Reputation: 375

That's because the hashes are the same, see this post. Hashes don't really have a concept of order, when you call the sort_by method it is converting the data to an array, ordering the array, and then returning an array. If you are converting the array to a hash you will lose the order essentially.

If you care about the order here, remove the to_h and just deal with the data as an array instead. Then your tests should work.

You can use .to_a in the test, and you don't need reverse in the sort.

view_counter.sort_by { |route, length| -length }

let(:result) do
  {
    "/help_page/1" => 3,
    "/about/2" => 1,
    "/contact" => 1,
    "/home" => 1,
    "/index" => 2,
  }.to_a
end

Upvotes: 1

Related Questions