laahaa
laahaa

Reputation: 347

DRY double in RSpec

How to DRY(don't repeat yourself) the double in RSpec? For example:

let(:s1) {instance_double(Class1,
                            :attr1 => val1,
                            :attr2 => val2,
                            :attr3 => val3,
                            :attr4 => val4,
                            :attr5 => val5)}


let(:s2) {instance_double(Class1,
                            :attr1 => val0, # the only difference between s2 and s1
                            :attr2 => val2,
                            :attr3 => val3,
                            :attr4 => val4,
                            :attr5 => val5)}

let(:s3) {instance_double(Class1,
                            :attr1 => val6, # the only difference between s3 and s1
                            :attr2 => val2,
                            :attr3 => val3,
                            :attr4 => val4,
                            :attr5 => val5)}

These 3 doubles are very similar and it seems we can refactor. But I tried:

  1. to make a basic hash for them:

    basic_hash = {attr2 => val2, attr3 => val3, attr4 => val4, attr5 => val5}

And then modified this basic hash and pass it into instance_double, for example, pass it into :s1:

basic_hash_s1 = basic_hash.clone
basic_hash_s1[:attr1] = val1
let(:s3) {instance_double(Class1, basic_hash_s1)

But this doesn't work. I'm working on an existing project and the Rspec didn't give any error message(maybe the project has some setting?), it just jumped the whole spec file.

  1. I also tried to allow on double:

    allow(s1).to receive(:attr).and_return(val1)

It still doesn't work.

Somebody know how to refactor this? Thanks!

======= edit =======

I tried to create double Hash object and pass it into :s1, it can be passed, but I don't know how to modify the content in that double: I tried to modify it as the same way as modifying a regular Hash object but it didn't work.

Upvotes: 2

Views: 463

Answers (2)

adrienbourgeois
adrienbourgeois

Reputation: 432

let(:opts) { { :attr1 => val1,
              :attr2 => val2,
              :attr3 => val3,
              :attr4 => val4,
              :attr5 => val5 } }

let(:s1) { instance_double(Class1, opts) }
let(:s2) { instance_double(Class1, opts.merge(:attr1 => val0)) }
let(:s3) { instance_double(Class1, opts.merge(:attr1 => val6)) }

Upvotes: 4

Fabio
Fabio

Reputation: 32443

Use a function

let(:create_s) do
    -> |attr1| do
         instance_double(Class1,
                        :attr1 => attr1
                        :attr2 => val2
                        :attr3 => val3
                        :attr4 => val4
                        :attr5 => val5)
    end
end

let(:s1) { create_s.call(val1) }
let(:s2) { create_s.call(val0) }
let(:s3) { create_s.call(val6) }

Upvotes: 2

Related Questions