Lazy testing
<p>You can test your associations lazily. Lazy isn’t always a bad thing, and for some situations,
it works perfectly.
1 2 3 4 5 6 |
# has_many side foo.should respond_to(:bars) # belongs_to side bar.should respond_to(:foo) |
<p>This does work.. kinda. But it doesn’t feel right because we aren’t actually asserting
that bars and foo are associations.
<h4> Custom matcher</h4>
<p>While researching links for this post, I found some interesting code at the
spicycode blog. It appears we have the same idea with completely different implementations. I’m going to show my partial solution here, and you can venture yonder if you want to see it from another point of view.
1 2 3 4 5 6 |
# Simply put, I wanted to do the following: foo.should have_many(Bar) # and I wanted to do this too: foo.should have_many(Bar).as(:quirks) |
<p>So, I shelled out some code..</p>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# matchers are plain old ruby classes class BeAHasMany # this is what the matcher is called on. # In this case: # foo.should have_many(:bars) # foo would be passed to the +initialize+ def initialize(expected) @expected = expected end # the work horse of the class. # # peforms the actual matching using the option +as+ method if applicable. def matches?(actual) @actual = actual association_name = @as.nil? ? @expected.to_s.tableize : @as reflection = actual.reflect_on_association(association_name.to_sym) if reflection.macro == :has_many reflection.klass == @expected else false end end # allows you to change the name of the assocation # example: # foo.should have_many(Bar).as(:quirks) def as(a) @as = a self end # error message for should def failure_message "expected #{@actual.inspect} to have_many #{@expected.inspect}, but it didn't" end # error message for should_not def negative_failure_message "expected #{@actual.inspect} not to have_many #{@expected.inspect}, but it did" end end # This method is the one you use with should/should_not def have_many(expected) BeAHasMany.new(expected) end |