Class: RR::DoubleCreator

Inherits:
Object
  • Object
show all
Includes:
Errors
Defined in:
lib/rr/double_creator.rb

Overview

RR::DoubleCreator provides a strategies to create a Double. The strategies are:

  • mock

  • stub

  • proxy

  • dont_allow

Constant Summary collapse

NO_SUBJECT_ARG =
Object.new

Constants included from Errors

Errors::BACKTRACE_IDENTIFIER

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(space) ⇒ DoubleCreator

Returns a new instance of DoubleCreator.



14
15
16
17
18
19
20
# File 'lib/rr/double_creator.rb', line 14

def initialize(space)
  @space = space
  @strategy = nil
  @proxy = false
  @instance_of = nil
  @instance_of_method_name = nil
end

Instance Attribute Details

#spaceObject (readonly)

Returns the value of attribute space.



11
12
13
# File 'lib/rr/double_creator.rb', line 11

def space
  @space
end

Instance Method Details

#create!(subject, method_name, *args, &handler) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rr/double_creator.rb', line 189

def create!(subject, method_name, *args, &handler)
  @args = args
  @handler = handler
  if @instance_of
    setup_class_probing_instances(subject, method_name)
  else
    setup_double(subject, method_name)
  end
  transform!
  @definition
end

#dont_allow(subject = NO_SUBJECT_ARG, method_name = nil, &definition) ⇒ Object Also known as: do_not_allow, dont_call, do_not_call

This method sets the Double to have a dont_allow strategy. A dont_allow strategy sets the default state of the Double to expect never to be called. The Double’s expectations can be changed.

The following example sets the expectation that subject.method_name will never be called with arg1 and arg2.

dont_allow(subject).method_name(arg1, arg2)

dont_allow also supports a block sytnax.

dont_allow(subject) do |m|
  m.method1 # Do not allow method1 with any arguments
  m.method2(arg1, arg2) # Do not allow method2 with arguments arg1 and arg2
  m.method3.with_no_args # Do not allow method3 with no arguments
end


107
108
109
110
111
112
113
# File 'lib/rr/double_creator.rb', line 107

def dont_allow(subject=NO_SUBJECT_ARG, method_name=nil, &definition)
  strategy_error! if @strategy
  proxy_when_dont_allow_error! if @proxy
  @strategy = :dont_allow
  return self if subject.__id__ === NO_SUBJECT_ARG.__id__
  RR::Space.double_method_proxy(self, subject, method_name, &definition)
end

#instance_of(subject = NO_SUBJECT_ARG, method_name = nil, &definition) ⇒ Object

Calling instance_of will cause all instances of the passed in Class to have the Double defined.

The following example mocks all User’s valid? method and return false.

mock.instance_of(User).valid? {false}

The following example mocks and proxies User#projects and returns the first 3 projects.

mock.instance_of(User).projects do |projects|
  projects[0..2]
end

Raises:

  • (ArgumentError)


182
183
184
185
186
187
# File 'lib/rr/double_creator.rb', line 182

def instance_of(subject=NO_SUBJECT_ARG, method_name=nil, &definition)
  @instance_of = true
  return self if subject === NO_SUBJECT_ARG
  raise ArgumentError, "instance_of only accepts class objects" unless subject.is_a?(Class)
  RR::Space.double_method_proxy(self, subject, method_name, &definition)
end

#mock(subject = NO_SUBJECT_ARG, method_name = nil, &definition) ⇒ Object

This method sets the Double to have a mock strategy. A mock strategy sets the default state of the Double to expect the method call with arguments exactly one time. The Double’s expectations can be changed.

This method can be chained with proxy.

mock.proxy(subject).method_name_1
or
proxy.mock(subject).method_name_1

When passed the subject, a DoubleMethodProxy is returned. Passing a method with arguments to the proxy will set up expectations that the a call to the subject’s method with the arguments will happen.

mock(subject).method_name_1 {return_value_1}
mock(subject).method_name_2(arg1, arg2) {return_value_2}

When passed the subject and the method_name, this method returns a mock Double with the method already set.

mock(subject, :method_name_1) {return_value_1}
mock(subject, :method_name_2).with(arg1, arg2) {return_value_2}

mock also takes a block for definitions.

mock(subject) do
  method_name_1 {return_value_1}
  method_name_2(arg_1, arg_2) {return_value_2}
end


49
50
51
52
53
54
# File 'lib/rr/double_creator.rb', line 49

def mock(subject=NO_SUBJECT_ARG, method_name=nil, &definition)
  strategy_error! if @strategy
  @strategy = :mock
  return self if subject.__id__ === NO_SUBJECT_ARG.__id__
  RR::Space.double_method_proxy(self, subject, method_name, &definition)
end

#proxy(subject = NO_SUBJECT_ARG, method_name = nil, &definition) ⇒ Object Also known as: probe

This method add proxy capabilities to the Double. proxy can be called with mock or stub.

mock.proxy(controller.template).render(:partial => "my/socks")

stub.proxy(controller.template).render(:partial => "my/socks") do |html|
  html.should include("My socks are wet")
  html
end

mock.proxy(controller.template).render(:partial => "my/socks") do |html|
  html.should include("My socks are wet")
  "My new return value"
end

mock.proxy also takes a block for definitions.

mock.proxy(subject) do
  render(:partial => "my/socks")

  render(:partial => "my/socks") do |html|
    html.should include("My socks are wet")
    html
  end

  render(:partial => "my/socks") do |html|
    html.should include("My socks are wet")
    html
  end

  render(:partial => "my/socks") do |html|
    html.should include("My socks are wet")
    "My new return value"
  end
end

Passing a block to the Double (after the method name and arguments) allows you to intercept the return value. The return value can be modified, validated, and/or overridden by passing in a block. The return value of the block will replace the actual return value.

mock.proxy(controller.template).render(:partial => "my/socks") do |html|
  html.should include("My socks are wet")
  "My new return value"
end


163
164
165
166
167
168
# File 'lib/rr/double_creator.rb', line 163

def proxy(subject=NO_SUBJECT_ARG, method_name=nil, &definition)
  proxy_when_dont_allow_error! if @strategy == :dont_allow
  @proxy = true
  return self if subject.__id__ === NO_SUBJECT_ARG.__id__
  RR::Space.double_method_proxy(self, subject, method_name, &definition)
end

#stub(subject = NO_SUBJECT_ARG, method_name = nil, &definition) ⇒ Object

This method sets the Double to have a stub strategy. A stub strategy sets the default state of the Double to expect the method call with any arguments any number of times. The Double’s expectations can be changed.

This method can be chained with proxy.

stub.proxy(subject).method_name_1
or
proxy.stub(subject).method_name_1

When passed the subject, a DoubleMethodProxy is returned. Passing a method with arguments to the proxy will set up expectations that the a call to the subject’s method with the arguments will happen, and return the prescribed value.

stub(subject).method_name_1 {return_value_1}
stub(subject).method_name_2(arg_1, arg_2) {return_value_2}

When passed the subject and the method_name, this method returns a stub Double with the method already set.

mock(subject, :method_name_1) {return_value_1}
mock(subject, :method_name_2).with(arg1, arg2) {return_value_2}

stub also takes a block for definitions.

stub(subject) do
  method_name_1 {return_value_1}
  method_name_2(arg_1, arg_2) {return_value_2}
end


84
85
86
87
88
89
# File 'lib/rr/double_creator.rb', line 84

def stub(subject=NO_SUBJECT_ARG, method_name=nil, &definition)
  strategy_error! if @strategy
  @strategy = :stub
  return self if subject.__id__ === NO_SUBJECT_ARG.__id__
  RR::Space.double_method_proxy(self, subject, method_name, &definition)
end