Skip to content

Commit

Permalink
added ruby syntax highlighting for github
Browse files Browse the repository at this point in the history
  • Loading branch information
icambron committed Nov 27, 2011
1 parent 6d93edd commit a13dd64
Showing 1 changed file with 37 additions and 1 deletion.
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,61 +15,77 @@ A Test Double is an object that stands in for a real object in a test.
RSpec creates test doubles that support method stubs and message
expectations.

```ruby
book = double("book")
```

## Method Stubs

A method stub is an implementation that returns a pre-determined value. Method
stubs can be declared on test doubles or real objects using the same syntax.
rspec-mocks supports 3 forms for declaring method stubs:

```ruby
book.stub(:title) { "The RSpec Book" }
book.stub(:title => "The RSpec Book")
book.stub(:title).and_return("The RSpec Book")
```

You can also use this shortcut, which creates a test double and declares a
method stub in one statement:

```ruby
book = double("book", :title => "The RSpec Book")
```

The first argment is a name, which is used for documentation and appears in
failure messages. If you don't care about the name, you can leave it out,
making the combined instantiation/stub declaration very terse:

```ruby
double(:foo => 'bar')
```

This is particularly nice when providing a list of test doubles to a method
that iterates through them:

```ruby
order.calculate_total_price(stub(:price => 1.99),stub(:price => 2.99))
```

## Consecutive return values

When a stub might be invoked more than once, you can provide additional
arguments to `and_return`. The invocations cycle through the list. The last
value is returned for any subsequent invocations:

```ruby
die.stub(:roll).and_return(1,2,3)
die.roll # => 1
die.roll # => 2
die.roll # => 3
die.roll # => 3
die.roll # => 3
```

To return an array in a single invocation, declare an array:

```ruby
team.stub(:players).and_return([stub(:name => "David")])
```

## Message Expectations

A message expectation is an expectation that the test double will receive a
message some time before the example ends. If the message is received, the
expectation is satisfied. If not, the example fails.

```ruby
validator = double("validator")
validator.should_receive(:validate).with("02134")
zipcode = Zipcode.new("02134", validator)
zipcode.valid?
```

## Nomenclature

Expand All @@ -94,21 +110,25 @@ behaviour in the context of a test. This technique is very common in Ruby
because we often see class objects acting as global namespaces for methods.
For example, in Rails:

```ruby
person = double("person")
Person.stub(:find) { person }
```

In this case we're instrumenting Person to return the person object we've
defined whenever it receives the `find` message. We can do this with any
object in a system because rspec-mocks adds the `stub` and `should_receive`
methods to every object. When we use either, RSpec replaces the method
we're stubbing or mocking with it's own test-double-like method. At the
we're stubbing or mocking with its own test-double-like method. At the
end of the example, RSpec verifies any message expectations, and then
restores the original methods.

## Expecting Arguments

```ruby
double.should_receive(:msg).with(*args)
double.should_not_receive(:msg).with(*args)
```

## Argument Matchers

Expand All @@ -122,6 +142,7 @@ you are free to create your own custom RSpec::Matchers.
rspec-mocks also adds some keyword Symbols that you can use to
specify certain kinds of arguments:

```ruby
double.should_receive(:msg).with(no_args())
double.should_receive(:msg).with(any_args())
double.should_receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can any kind of Numeric
Expand All @@ -130,9 +151,11 @@ specify certain kinds of arguments:
double.should_receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all
double.should_receive(:msg).with(1, ducktype(:abs, :div), "b")
#2nd argument can be object that responds to #abs and #div
```

## Receive Counts

```ruby
double.should_receive(:msg).once
double.should_receive(:msg).twice
double.should_receive(:msg).exactly(n).times
Expand All @@ -143,24 +166,30 @@ specify certain kinds of arguments:
double.should_receive(:msg).at_most(:twice)
double.should_receive(:msg).at_most(n).times
double.should_receive(:msg).any_number_of_times
```

## Ordering

```ruby
double.should_receive(:msg).ordered
double.should_receive(:other_msg).ordered
#This will fail if the messages are received out of order
```

## Setting Reponses

Whether you are setting a message expectation or a method stub, you can
tell the object precisely how to respond. The most generic way is to pass
a block to `stub` or `should_receive`:

```ruby
double.should_receive(:msg) { value }
```

When the double receives the `msg` message, it evaluates the block and returns
the result.

```ruby
double.should_receive(:msg).and_return(value)
double.should_receive(:msg).exactly(3).times.and_return(value1, value2, value3)
# returns value1 the first time, value2 the second, etc
Expand All @@ -171,15 +200,18 @@ the result.
double.should_receive(:msg).and_yield(values,to,yield)
double.should_receive(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
# for methods that yield to a block multiple times
```

Any of these responses can be applied to a stub as well

```ruby
double.stub(:msg).and_return(value)
double.stub(:msg).and_return(value1, value2, value3)
double.stub(:msg).and_raise(error)
double.stub(:msg).and_throw(:msg)
double.stub(:msg).and_yield(values,to,yield)
double.stub(:msg).and_yield(values,to,yield).and_yield(some,other,values,this,time)
```

## Arbitrary Handling

Expand All @@ -188,16 +220,20 @@ particular problem you are trying to solve. Imagine that you expect the message
to come with an Array argument that has a specific length, but you don't care
what is in it. You could do this:

```ruby
double.should_receive(:msg) do |arg|
arg.size.should eq(7)
end
```

## Combining Expectation Details

Combining the message name with specific arguments, receive counts and responses
you can get quite a bit of detail in your expectations:

```ruby
double.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError)
```

While this is a good thing when you really need it, you probably don't really
need it! Take care to specify only the things that matter to the behavior of
Expand Down

0 comments on commit a13dd64

Please sign in to comment.