Sidekiq - Minitest error: NoMethodError: unmocked method :==, expected one of  #1291
there has been a bug report on the mailing list that specs fail on JRuby for the beloved sidekiq project for JRuby. Specs pass with Ruby 1.9.3 and 2.0. It seems like the bug manifests in the minitest library but I haven't done any kind of deep investigation.
The error message is this (as observed in this build and locally, jruby version 1.7.8):
The error occurs during the following spec (no before hooks or something that I am aware of):
it 'assigns work to a processor' do uow = Minitest::Mock.new processor = Minitest::Mock.new processor.expect(:async, processor, ) processor.expect(:process, nil, [uow]) mgr = Sidekiq::Manager.new(options) mgr.ready << processor mgr.assign(uow) assert_equal 1, mgr.busy.size processor.verify # stack trace originates here end
JRuby is on the allowed failures for sidekiq, would be great to get it out of there,
The text was updated successfully, but these errors were encountered:
To follow on to Tobi's comments, the spec in question (and similar specs) pass on MRI. The reason for the failure appears to be that in JRuby '==' is called for objects in an Array, while the '==' method is not on the automatically permitted method list for Minitest::Mock objects.
Here's a simple spec, not Sidekiq specific, that fails with this exception:
From examining the code it looks like MRI might be using '===' for comparing the individual elements in an array. I'm not sure if this is correct, but rb_equal is being called on the individual elements of the two arrays and the comments indicate that this method corresponds to '==='
Ok I have a theory but I want to reduce this a bit more. I think you are correct that rb_equal is being called but I think it is being called directly in C and is not a Ruby dispatch. Since the test case is two identical objects in the array the first if statement in rb_equal will just return out without performing ==. In JRuby, we seem to always be calling == and we do not have this short-cut. I can easily get MRI to match our behavior:
gem 'minitest' require 'minitest/mock' item = Minitest::Mock.new item2 = Minitest::Mock.new [item] == [item2]
We will fix this and their optimization reduces dynamic dispatches but from a mocking perspective their behavior feels inconsistent. OTOH, I have not fully fixed this yet so my theory could be wrong.