我应该测试这种方法的哪种行为?

时间:2014-05-18 13:18:03

标签: ruby-on-rails ruby rspec tdd sinatra

我想测试save方法:

class Note
  def initialize(password)
    @password = password
  end

  def save
    encryption = Note::Encryption.new(@password)
    encrypted   = encryption.encrypt(serialized)

    storage = Note::Storage.new

    storage.write(encrypted)
  end

  private
  def serialized
    {some_data: true}
  end
  # .....
end

方法主要将工作委托给其他课程,这是唯一的责任。我测试它的第一个赌注就是检查:

  describe '#save' do
    let(:encryption){ '12345' }
    it 'calls encryption' do
      expect_any_instance_of(Note::Encryption).to receive(:encrypt)
      subject.save
    end

    it 'saves the file with data' do
      expect_any_instance_of(Note::Storage).to receive(:write)
      subject.save
    end
  end

我对这种方法有疑问,因为我有点担心这些测试不会测试太多......而且现在测试很高,再加上实现不行为。有谁知道如何处理这种方法。值得一提的是,这个类在包装一些资源时会位于系统的顶层。

2 个答案:

答案 0 :(得分:2)

我会测试一下,因为我想确定传递给那些方法的参数:

class Note
  def initialize(password)
    @password = password
  end

  def save
    encrypted = Note::Encryption.new(@password).encrypt(serialized)
    Note::Storage.new.write(encrypted)
  end

private

  def serialized
    {some_data: true}
  end
end

# the test
describe '#save' do
  let(:password) { 'secret password' }
  let(:encryted) { 'encrytped string' }
  let(:storage) { double(:write => true) }
  let(:note_encryption) { double(:encrypt => encrypted) }

  subject(:note) { Note.new(password) }

  before do
    allow(Note::Encryption).to receive(:new).with(password).and_return(note_encryption)
    Note::Storage.stub(:new => storage)
  end

  it 'encrypted the password' do
    note.save
    expect(Note::Encryption).to have_received(:new).with(password)
    expect(note_encryption).to have_received(:encrypt).with(serialized) # mock serialized?
  end

  it 'stores the encryted string' do
    note.save
    expect(storage).to have_received(:write).with(encrypted)
  end
end

答案 1 :(得分:0)

如果你看一下这个方法,它会做一些不连续的事情:

def save
  encryption = Note::Encryption.new(@password)
  encrypted   = encryption.encrypt(serialized) # first action

  storage = Note::Storage.new

  storage.write(encrypted) # second action
end

这些是你应该测试的东西,以及验证 - 如果@password是一个空字符串会发生什么?

测试看起来像这样:

let(:password) { 'my_pass' }
let(:note)     { Note.new(password) }
let(:result)   { note.save }

describe 'save' do 
  describe 'with a blank password' do
    let(:password) { '' }

    it 'fails' do 
      # assert_raises...
    end
  end

  it 'encrypts the password' do 
    refute_same password, result  #of course, this depends on what Storage.write returns...
  end

  it 'saves the password' do 
    # assert that the password is saved
  end

end

另外,如果我可以建议一个重构 -

class Note
  def initialize(password)
    @password = password
  end

  def save
    encrypted = build_encrypted_object
    storage.write(encrypted)
  end

  private
  def build_encrypted_object
    encryption.encrypt(serialized)
  end

  def serialized
    {some_data: true}
  end

  def encryption
    Note::Encryption.new(@password)
  end

  def storage
    Note::Storage.new
  end

  # .....
end