Picking up where I left off last night I need to build up the meal listing for a given year. I plan to ask a CouchDB view for this list. The example describing this is:
it "should ask CouchDB for meal from year YYYY" doThat's pretty straight forward—a request of the Sinatra "/meals/2009" action should, in turn, fire off a request to the (as yet unwritten) CouchDB view that will accept a parameter of
RestClient.
should_receive(:get).
with(/year=2009/).
and_return("{ }")
get "/meals/2009"
end
year=2009
. Before implementing this example, I run the spec to determine if I need to change the message or make it pass:cstrom@jaynestown:~/repos/eee-code$ spec ./spec/eee_spec.rbUnfortunately, I need to change an entirely unexpected message here. I have yet to add any code to the Sinatra action, so where on earth is that
.F...............
1)
Spec::Mocks::MockExpectationError in 'eee a CouchDB meal GET /meals/YYYY should ask CouchDB for meal from year YYYY'
RestClient expected :get with (/year=2009/) but received it with ("http://localhost:5984/eee-test/id-2009-05-13")
./spec/eee_spec.rb:36:
Finished in 0.207576 seconds
17 examples, 1 failure
RestClient#get
originating?The answer is the
after(:each)
block that is responsible for tearing down the meal(s) created for the examples:after(:each) doOh man, I need to
data = RestClient.get "#{@@db}/#{@permalink}"
meal = JSON.parse(data)
RestClient.delete "#{@@db}/#{@permalink}?rev=#{meal['_rev']}"
end
get
twice—once in the example and once in the after(:each)
tear down—but I want to stub one call and let the other pass through to the DB. That does not sound easy.The best that I can come up with is to un-stub the second call to
RestClient#get
by invoking the alias created by RSpec. When RSpec assigns a stub or expectation, it performs an alias_method_chain
-like renaming of the original method by prefixing it with proxied_by_rspec__
. Thus, the original, non-stubbed version of RestClient#get
is available as RestClient#proxied_by_rspec__get
.Putting this knowledge to use, I can leave the expectation in the example, but modify the
after(:each)
example code block to make a real RestClient#get
request:after(:each) doSadly, with that in place, I am in even worse shape than before:
data = RestClient.proxied_by_rspec__get "#{@@db}/#{@permalink}"
meal = JSON.parse(data)
RestClient.delete "#{@@db}/#{@permalink}?rev=#{meal['_rev']}"
end
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/eee_spec.rbGak! I do not have a stub in my first example, so there is no
FF...............
1)
NoMethodError in 'eee a CouchDB meal GET /meals/YYYY should respond OK'
undefined method `proxied_by_rspec__get' for RestClient:Module
./spec/eee_spec.rb:35:
2)
RestClient::RequestFailed in 'eee a CouchDB meal GET /meals/YYYY should ask CouchDB for meal from year YYYY'
HTTP status code 409
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:144:in `process_result'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:106:in `transmit'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:103:in `transmit'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:36:in `execute_inner'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:28:in `execute'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:12:in `execute'
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient.rb:65:in `put'
./spec/eee_spec.rb:29:
Finished in 0.230206 seconds
17 examples, 2 failures
RestClient#proxied_by_rspec__get
method available in the after(:each)
block. Since the meal is not deleted after the first example, it is still in place when the second example tries to create it, which is the reason for the second failure.To change this message I need to add a stub in the
before(:each)
block to pair with the un-stub in the after(:each)
block:before(:each) doFinally, I get the failure that I was expecting from the outset—the
@date = Date.new(2009, 5, 13)
@title = "Meal Title"
@permalink = "id-#{@date.to_s}"
meal = {
:title => @title,
:date => @date,
:serves => 4,
:summary => "meal summary",
:description => "meal description"
}
RestClient.put "#{@@db}/#{@permalink}",
meal.to_json,
:content_type => 'application/json'
RestClient.stub!(:get).and_return("{ }")
end
RestClient
call to CouchDB has not yet been implemented:cstrom@jaynestown:~/repos/eee-code$ spec ./spec/eee_spec.rbNow, instead of changing the message, I can make it pass by adding the
.F...............
1)
Spec::Mocks::MockExpectationError in 'eee a CouchDB meal GET /meals/YYYY should ask CouchDB for meal from year YYYY'
RestClient expected :get with (/year=2009/) once, but received it 0 times
./spec/eee_spec.rb:51:
Finished in 0.167963 seconds
17 examples, 1 failure
RestClient
call:get %r{/meals/(\d+)} do |year|And, indeed, it is now passing:
url = "#{@@db}/_design/meals/_view/by_year?group=true&year=#{year}}"
data = RestClient.get url
@meals = JSON.parse(data)
end
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/eee_spec.rbThat is a good stopping point for tonight. I would have preferred to have made some progress on the views (Haml and CouchDB), but I know where to pick up tomorrow.
.................
Finished in 1.838225 seconds
17 examples, 0 failures
(commit)
No comments:
Post a Comment