Kenneth Jiang Kenneth Jiang - 3 months ago 9
Ruby Question

How can I DRY up assertions that a method is called with an expected argument?

I need to write examples that test an argument passed to a method.

Option #1 is to return the received argument as subject so that the verification part can be very concise:

subject do
color = nil
pen_double.should_receive(:color=) do |arg|
color = arg
end
color
end

context ...
it { should == 'red' }
end

context ...
it { should == 'green' }
end


The problem with this option is that the "subject" part is bulky. And it becomes big problem when I start to test other methods (there are many methods that need to be tested).

Option #2 is not to use "subject". instead it reads:

context ...
it { pen_double.should_receive(:color=).with('red') }
end

context ...
it { pen_double.should_receive(:color=).with('green') }
end


Obviously now the 'it' part is not DRY enough.

Is there a 3rd option that I overlooked?

Answer

It's not really a different option, but you can improve option 2 by extracting a helper method:

context ...
  it { should_be_set_to 'red' }
end

context ...
  it { should_be_set_to 'green' }
end

def should_be_set_to(color)
  pen_double.should_receive(:color=).with color
end

That is DRY, more concise than doing it with a subject block, and can be understood to a degree without reading the helper method. (You can probably come up with a better method name than I can, since you know the domain.)

Comments