[rspec-users] some fun functionality for all your specs

David Chelimsky dchelimsky at gmail.com
Fri Feb 16 19:08:24 EST 2007


On 2/16/07, Courtenay <court3nay at gmail.com> wrote:
> I've found these two snippets of code useful and would love some feedback.
>
> first, .should_have_valid_associations
> usage:
>
> context "A new Product" do
>   specify "should have valid associations" do
>     @product.should_have_valid_associations
>   end
> end
>
> code: (thanks to Wilson/Defiler for converting to rspec)
>
> module Spec
>   module Expectations
>     module Should
>       class Base
>         def have_valid_associations
>           @target.save_without_validation
>           @target.class.reflect_on_all_associations.each do |assoc|
>             lambda { @target.send(assoc.name, true) }.should_not_raise
>           end
>           self
>         end
>       end
>     end
>   end
> end

A couple of things. First, VERY COOL. Second, here's how you can do it
in 0.8 and later (coming soon):

module ActiveRecordExpectations
  def have_valid_associations
    return Class.new do
      def matches?(model)
        @model = model
        @model.save_without_validation
        @invalid_associations = []
        @target.class.reflect_on_all_associations.each do |assoc|
          begin
            @target.send(assoc.name, true)
          rescue
            @invalid_associations << assoc
          end
        end
        @invalid_associations.empty?
      end

      def failure_message
        "expected all valid associations, but the following were not
valid: #{@invalid_associations.inspect}"
      end
    end
  end.new
end

context "A new Product" do
  include ActiveRecordExpectations
  specify "should have valid associations" do
    @product.should have_valid_associations
  end
end

The nice thing here is that you can give it better failure messages.
Also, the expectation is not monkey patched onto Object.

WDYT?

>
>
> second, I had a problem where I'd renamed some fields in the model and
> didn't want to manually spec out each method, but also didn't want to
> go the 'null object' route.    assigns[:cart] = @cart = mock("cart")
>
>     @cart.stub!(:attr_name).and_return('cart')
>     @cart.stub!(:to_param).and_return('99')
>     @cart.stub!(:class).and_return(Cart)
>
>     Cart.content_columns.each { |c|
>       @cart.stub!(c.name.to_sym)
>     }
>     Cart.reflect_on_all_associations.each do |assoc|
>       @cart.stub!(assoc.name.to_sym).and_return([])
>     end
>     @cart.stub!(:name).and_return('cart')
>
> As you can see it rapidly spirals out of control, but this snippet
> sets up all the associations and field names as stubs.
>

Cool. We just added a mock_model method that does some similar stuff
but on an instance of Mock (not an instance of a Model). This would be
a good addition, wrapped in a method named stub_model:

stub_model(Person)

Would you consider submitting a patch w/ this method added to
Spec::Rails::Runner::EvalContext?

David

> Comments?
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list