Blob of rspec_on_rails/lib/spec/rails/example/rails_example_group.rb (raw blob data)

1 require 'spec/interop/test'
2
3
4 ActionView::Base.cache_template_extensions = false
5
6 module Spec
7 module Rails
8
9 class IllegalDataAccessException < StandardError; end
10
11 module Example
12 class RailsExampleGroup < Test::Unit::TestCase
13 # Rails >= r8570 uses setup/teardown_fixtures explicitly
14 before(:each) do
15 setup_fixtures if self.respond_to?(:setup_fixtures)
16 end
17 after(:each) do
18 teardown_fixtures if self.respond_to?(:teardown_fixtures)
19 end
20
21 include Spec::Rails::Matchers
22
23 # Creates a mock object instance for a +model_class+ with common
24 # methods stubbed out. Additional methods may be easily stubbed (via
25 # add_stubs) if +stubs+ is passed.
26 def mock_model(model_class, options_and_stubs = {})
27 id = next_id
28 options_and_stubs = {
29 :id => id,
30 :to_param => id.to_s,
31 :new_record? => false,
32 :errors => stub("errors", :count => 0)
33 }.merge(options_and_stubs)
34 m = mock("#{model_class.name}_#{id}", options_and_stubs)
35 m.send(:__mock_proxy).instance_eval <<-CODE
36 def @target.is_a?(other)
37 #{model_class}.ancestors.include?(other)
38 end
39 def @target.kind_of?(other)
40 #{model_class}.ancestors.include?(other)
41 end
42 def @target.instance_of?(other)
43 other == #{model_class}
44 end
45 def @target.class
46 #{model_class}
47 end
48 CODE
49 yield m if block_given?
50 m
51 end
52
53 # :call-seq:
54 # stub_model(Model)
55 # stub_model(Model).as_new_record
56 # stub_model(Model, hash_of_stubs)
57 #
58 # Creates an instance of +Model+ that is prohibited from accessing the
59 # database. For each key in +hash_of_stubs+, if the model has a
60 # matching attribute (determined by asking it, which it answers based
61 # on schema.rb) are simply assigned the submitted values. If the model
62 # does not have a matching attribute, the key/value pair is assigned
63 # as a stub return value using RSpec's mocking/stubbing framework.
64 #
65 # new_record? is overridden to return the result of id.nil? This means
66 # that by default new_record? will return false. If you want the
67 # object to behave as a new record, sending it +as_new_record+ will
68 # set the id to nil. You can also explicitly set :id => nil, in which
69 # case new_record? will return true, but using +as_new_record+ makes
70 # the example a bit more descriptive.
71 #
72 # While you can use stub_model in any example (model, view,
73 # controller, helper), it is especially useful in view examples,
74 # which are inherently more state-based than interaction-based.
75 #
76 # == Examples
77 #
78 # stub_model(Person)
79 # stub_model(Person).as_new_record
80 # stub_model(Person, :id => 37)
81 # stub_model(Person) do |person|
82 # model.first_name = "David"
83 # end
84 def stub_model(model_class, stubs = {})
85 stubs = {:id => next_id}.merge(stubs)
86 returning model_class.new do |model|
87 model.id = stubs.delete(:id)
88 (class << model; self; end).class_eval do
89 def connection
90 raise IllegalDataAccessException.new("stubbed models are not allowed to access the database")
91 end
92 def new_record?
93 id.nil?
94 end
95 def as_new_record
96 self.id = nil
97 self
98 end
99 end
100 stubs.each do |k,v|
101 if model.has_attribute?(k)
102 model[k] = stubs.delete(k)
103 end
104 end
105 add_stubs(model, stubs)
106 yield model if block_given?
107 end
108 end
109 #--
110 # TODO - Shouldn't this just be an extension of stub! ??
111 # - object.stub!(:method => return_value, :method2 => return_value2, :etc => etc)
112 #++
113 # Stubs methods on +object+ (if +object+ is a symbol or string a new mock
114 # with that name will be created). +stubs+ is a Hash of <tt>method=>value</tt>
115 def add_stubs(object, stubs = {}) #:nodoc:
116 m = [String, Symbol].index(object.class) ? mock(object.to_s) : object
117 stubs.each {|k,v| m.stub!(k).and_return(v)}
118 m
119 end
120 Spec::Example::ExampleGroupFactory.default(self)
121
122 private
123 @@model_id = 1000
124 def next_id
125 @@model_id += 1
126 end
127 end
128 end
129 end
130 end