given I have the following with the internal assignments to filter and ldap:
class Collaborator
def self.search_ldap(term)
last_name = term.strip.split(/[, ]/).first.downcase
filter = Net::LDAP::Filter.eq(''surName'', last_name)
ldap = Net::LDAP.new( :host => ''foo'', :port => 636,
:base => ''bar'',
:encryption => :fiz)
ldap.search(:filter => filter)
end
end
I would like mock out the LDAP class so i can test the behavior of the
method without LDAP.
describe Collaborator do
it "should search ldap and return last names from the first item of the
search phrase" do
entry = Net::LDAP::Entry
items = {:cn=>["Jim
Bob"],:uid=>[''bob46''],:mail=>''bob at
life.edu''}
items.each{|k,v| entry.stub(k) {v} }
# how do I get to objects inside this method, something like?
assigns(:ldap).stub(:search).and_return(entry) # but that doesnt work
Collaborator.search_ldap("Bob").should == [entry]
end
end
--
Jed Schneider
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://rubyforge.org/pipermail/rspec-users/attachments/20110621/acdb7769/attachment.html>
J. B. Rainsberger
2011-Jun-21 21:56 UTC
[rspec-users] stubbing /mocking ldap within a method
On Tue, Jun 21, 2011 at 17:00, Jed Schneider <jed.schneider at gmail.com> wrote:> given I have the following with the internal assignments to filter and ldap: > class Collaborator > ??def self.search_ldap(term) > ?? ?last_name = term.strip.split(/[, ]/).first.downcase > ?? ?filter = Net::LDAP::Filter.eq(''surName'', last_name) > ?? ?ldap = Net::LDAP.new( :host => ''foo'', :port => 636, :base => ''bar'', > :encryption => :fiz) > ?? ?ldap.search(:filter => filter) > ??end > end > I would like mock out the LDAP class so i can test the behavior of the > method without LDAP.In this case, I''d invoke the rule "Don''t mock types you don''t own". What can you trust? LDAP does the right thing. What can you get wrong? Sending the wrong parameters to LDAP. Therefore, check the parameters you send to LDAP. class Collaborator def initialize(ldapGateway = LdapGateway.new) @gateway = ldapGateway end def self.search_ldap(term) last_name = term.strip.split(/[, ]/).first.downcase @gateway.search(''surName'', last_name, ''foo'', 636, ''bar'', :fiz) end end class LdapGateway def search(label, value, host, port, base, encryption) filter = Net::LDAP::Filter.eq(''surName'', last_name) ldap = Net::LDAP.new( :host => ''foo'', :port => 636, :base => ''bar'', :encryption => :fiz) ldap.search(:filter => filter) end end Judging only by the names, "label" and "value" seem separate from "host"?"encryption". My intuition tells me to move the latter group into constructor parameters. class Collaborator def initialize(ldapGateway) @gateway = ldapGateway end def self.search_ldap(term) last_name = term.strip.split(/[, ]/).first.downcase @gateway.search(''surName'', last_name) end end class LdapGateway def initialize(host, post, base, encryption) # assign to fields end def search(label, value) filter = Net::LDAP::Filter.eq(''surName'', last_name) # SMELL Temporal duplication; can we create an LDAP in the constructor? ldap = Net::LDAP.new( :host => @host, :port => @port, :base => @base, :encryption => @encryption) ldap.search(:filter => filter) end end Now the LdapGateway responds to search(label, value), so I don''t think Collaborator needs to know that any LDAP is going on. class Collaborator def initialize(term_repository) @term_repository = term_repository end def self.search_ldap(term) last_name = term.strip.split(/[, ]/).first.downcase @term_repository.search(''surName'', last_name) end end I''m using the mechanical name "Repository" here, because I don''t yet understand the role this object plays in the system. class LdapGateway # I''m a TermRepository! Extract a module someday? def initialize(host, post, base, encryption) # assign to fields end def search(label, value) filter = Net::LDAP::Filter.eq(''surName'', last_name) # SMELL Temporal duplication; can we create an LDAP in the constructor? ldap = Net::LDAP.new( :host => @host, :port => @port, :base => @base, :encryption => @encryption) ldap.search(:filter => filter) end end Now it''s easy to check: describe Collaborator do context "when searching" do it "should pass the proper surname to the TermRepository" do termRepository = mock("a TermRepository") termRepository.should_receive(:search).with(''surName'', ''rainsberger'') Collaborator.new(termRepository).search(''J. B. Rainsberger'') end it "should return the repository''s results" do Collaborator.new(stub(:search => ["a", "b", "c"])).search(''J. B. Rainsberger'').should == ["a", "b", "c"] end end end Does that help you? -- J. B. (Joe) Rainsberger :: http://www.jbrains.ca :: http://blog.thecodewhisperer.com Author, JUnit Recipes Free Your Mind to Do Great Work :: http://www.freeyourmind-dogreatwork.com
Joe,
Here is the solution I decided to go with, for now:
describe Collaborator do
describe "class_methods" do
subject {Collaborator}
it { should respond_to(:search_ldap).with(1).argument }
it "should format the search term" do
subject.prepare_search_term("Bob").should == "bob"
end
end
end
describe LdapGateway do
subject { LdapGateway.new("surName") }
it { should respond_to(:search_for).with(1).argument }
it "should set @ldap to an instance of Net::LDAP" do
subject.instance_eval(''@ldap'').should
be_kind_of(Net::LDAP)
end
it "should set the label to the initialzied variable" do
subject.instance_eval("@label").should == "surName"
end
end
class LdapGateway
def initialize(label)
@ldap = Net::LDAP.new(credentials)
@label = label
end
def search_for(term)
@ldap.search(:filter => Net::LDAP::Filter.eq(@label, term))
end
end
class Collaborator < ActiveRecord::Base
def self.search_ldap(term)
last_name = prepare_search_term(term)
@gateway = LdapGateway.new(''surName'')
@gateway.search_for(last_name)
# alternatively, maybe
# LdapGateway.new(''surName'').search_for(last_name)
end
def self.prepare_search_term(term)
term.strip.split(/[, ]/).first.downcase
end
end
--
Jed Schneider
706-207-4458 (m)
803-386-7214
jedschneider.posterous.com
twitter.com/jedschneider
github.com/jedschneider
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://rubyforge.org/pipermail/rspec-users/attachments/20110622/5544e7d2/attachment.html>