MiniTest::Mock 2、さらに例の分析

2802 ワード

mock stubやfakesの概念に慣れていなければ見てもいいそうです
これ私は自分で見たが、分からなかった.例を見たほうが簡単だ
例えば、テストが必要なものがあります.

class MailPurge
  def initialize(imap)
    @imap = imap
  end

  def purge(date)
    # IMAP wants dates in the format: 8-Aug-2002
    formatted_date = date.strftime('%d-%b-%Y')
  
    @imap.authenticate('LOGIN', 'user', 'password')
    @imap.select('INBOX')

    message_ids = @imap.search(["BEFORE #{formatted_date}"])
    @imap.store(message_ids, "+FLAGS", [:Deleted])
  end
end


私たちのmockはこのように使います

# mock imap authenticate select , ids 
def test_purging_mail
  date = Date.new(2010,1,1)
  formatted_date = '01-Jan-2010'
  ids = [4,5,6]
  
  mock = MiniTest::Mock.new
  
  # mock expects:
  #            method      return  arguments
  #-------------------------------------------------------------
  mock.expect(:authenticate,  nil, ['LOGIN', 'user', 'password'])
  mock.expect(:select,        nil, ['INBOX'])
  mock.expect(:search,        ids, [["BEFORE #{formatted_date}"]])
  mock.expect(:store,         nil, [ids, "+FLAGS", [:Deleted]])
  
  mp = MailPurge.new(mock)
  mp.purge(date)
  
  assert mock.verify
end


もし、足りないのが嫌なら、mockの勉強をしてもいいです.
ソースコード

def initialize
  @expected_calls = {}
  @actual_calls = Hash.new {|h,k| h[k] = [] }
end
# , 

def expect(name, retval, args=[])
  n, r, a = name, retval, args # for the closure below
  @expected_calls[name] = { :retval => retval, :args => args }
  self.class.__send__(:define_method, name) { |*x|
    raise ArgumentError unless @expected_calls[n][:args].size == x.size
    @actual_calls[n] << { :retval => r, :args => x }
    retval
  }
  self
end
# mock ,expect , , , , 

def verify
  @expected_calls.each_key do |name|
    expected = @expected_calls[name]
    msg = "expected #{name}, #{expected.inspect}"
    raise MockExpectationError, msg unless
      @actual_calls.has_key? name and @actual_calls[name].include?(expected)
  end
  true
end
#