On Tue, Jun 21, 2011 at 17:00, Jed Schneider <jed.schnei...@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 _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users