From: Brian Candler on 2 Aug 2010 09:53 Fernando Guillen wrote: > Is this possible?.. am I completely lost?.. is there any better way to > do this? I'd suggest you use an existing mocking library like "mocha". Example: -------- 8< ---------------- require 'net/pop' require 'test/unit' require 'rubygems' require 'mocha' # code to test class Foo attr_reader :opts def initialize(opts) @opts = opts end def bar(block) Net::POP3.start( opts[:server], opts[:port], opts[:user], opts[:pass] ) do |pop| pop.each_mail do |m| block.call( m ) end end end end # tests class MyTest < Test::Unit::TestCase def test_1 mails = ["xxxxx","yyy"] mockpop = mock mockpop.expects(:each_mail).multiple_yields(*mails) Net::POP3.expects(:start).with("127.0.0.1", 110, "a", "b").yields(mockpop) foo = Foo.new(:server=>"127.0.0.1", :port=>110, :user=>"a", :pass=>"b") res = [] foo.bar(lambda { |x| res << x.size }) assert_equal [5,3], res end # more expectation-based style def test_2 mails = ["xxxxx","yyy"] mockpop = mock mockpop.expects(:each_mail).multiple_yields(*mails) Net::POP3.expects(:start).with("127.0.0.1", 110, "a", "b").yields(mockpop) mockblock = mock seq = sequence(:block) mockblock.expects(:call).with(mails[0]).in_sequence(seq) mockblock.expects(:call).with(mails[1]).in_sequence(seq) foo = Foo.new(:server=>"127.0.0.1", :port=>110, :user=>"a", :pass=>"b") foo.bar(mockblock) end end -------- 8< ---------------- I find there's something unsatisfying about tests which look like this. Sometimes you can spend more effort on the mechanics of mocking than on solving the original problem, and the resulting tests are closely coupled to the internal implementation of your function. But that *is* what you asked for :-) Refactoring might make your code easier to test. e.g. -------- 8< ---------------- require 'net/pop' require 'test/unit' require 'rubygems' require 'mocha' class Foo attr_reader :opts def initialize(opts) @opts = opts end def bar(block) for_all_messages do |m| block.call(m) end end private def for_all_messages(&blk) Net::POP3.start( opts[:server], opts[:port], opts[:user], opts[:pass] ) do |pop| pop.each_mail(&blk) end end end class MyTest < Test::Unit::TestCase def test_1 foo = Foo.new({}) mails = ["xxxxx","yyy"] foo.expects(:for_all_messages).multiple_yields(*mails) res = [] foo.bar(lambda { |x| res << x.size }) assert_equal [5,3], res end end -------- 8< ---------------- HTH, Brian. -- Posted via http://www.ruby-forum.com/.
From: Fernando Guillen on 2 Aug 2010 10:12 Brian Candler wrote: > Fernando Guillen wrote: >> Is this possible?.. am I completely lost?.. is there any better way to >> do this? > > I'd suggest you use an existing mocking library like "mocha". This was how I started to try mock the Net::POP3. But instead of using the .yields method, that I didn't know about, I tried to mock directly the Net::POP3.start method and this didn't work. Thanks a lot for your comprehensive examples and also for the re-factoring suggestion for an easier mock. Best regards. f. -- Posted via http://www.ruby-forum.com/.
From: Brian Candler on 2 Aug 2010 10:31 Fernando Guillen wrote: > But instead of using the .yields method, that I didn't know about, I > tried to mock directly the Net::POP3.start method and this didn't work. It would be really useful if you could attach arbitrary behaviour to a mocked method - perhaps 'returns' with a block: m = [1,2,3] Net::POP3.expects(:start).returns { m.each { puts m }; m.size } This is something I've missed badly in the past, and I've ended up mocking directly using Object.new and defining singleton methods. -- Posted via http://www.ruby-forum.com/.
From: Fernando Guillen on 2 Aug 2010 12:22 Hi again people, Following your suggestions I am trying to build an small library to abstract this behavior on a reusable way: * http://github.com/fguillen/NetPopMock My problem now is that I'm not able to use the _raw_mails_ array sent on the **NetPopMock.fake** call See the test example: * http://github.com/fguillen/NetPopMock/blob/master/test/net_pop_mock_test.rb#L15 Into the mocked class: * http://github.com/fguillen/NetPopMock/blob/master/net_pop_mock.rb#L30 Jesus was the first one suggesting me to use _class_eval_ and I told him that I thought I was enough information to work on my self.. well that was not true.. I need help again :) I know the solution is in a mix of _eval_ and _binding_ but I don't find it. Thanks again f. -- Posted via http://www.ruby-forum.com/.
From: Fernando Guillen on 2 Aug 2010 12:27 Thinking I found the solution: * http://github.com/fguillen/NetPopMock/commit/7003aa7db33f98165a10987058ece171a7b371dd Do you think is a clean solution? Regards f. -- Posted via http://www.ruby-forum.com/.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Active Record Inheritance with out using type_id Next: Argument Error |