Pertanyaan Bagaimana saya bisa rintisan find_each untuk pengujian rspec di rel 3


Saya bertanya-tanya bagaimana menguji panggilan find_each di rspec. Saya sudah terbiasa untuk mematikan apa yang saya ingin model saya untuk kembali jadi saya tidak bergantung pada data tes di db seperti ini:

MyClass.stub(:find).and_return(my_mock)

Namun, di kelas lain saya melakukan ini:

MyClass.find_each do |instance_of_my_class|
  do_stuff_here_on(instance_of_my_class)
end

Saya menemukan bahwa jika saya melakukan ini:

MyClass.stub(:find_each).and_return([one_mock, two_mock])

dalam tes spek, bagian "lakukan di sini" tidak dieksekusi. Apakah ada yang tahu bagaimana cara mendeklarasikan find_each untuk pengujian rspec?


32
2017-12-07 23:18


asal


Jawaban:


Anda dapat menggunakan dan_yield untuk membuat rspec panggilan blok yang dilewatkan ke tiruan:

MyClass.stub(:find_each).and_yield(one_mock).and_yield(two_mock)

37
2017-12-08 07:15



Inti dari stubbing suatu metode adalah agar metode mengembalikan nilai yang diharapkan dan tidak mengeksekusi isinya. Jika Anda memiliki banyak logika dalam metode find_each, saya akan merekomendasikan memindahkannya ke metode terpisah dan menguji logika itu secara terpisah. Anda kemudian dapat menguji bahwa metode Anda dipanggil selama eksekusi.

Berikut contoh level yang cukup tinggi:

class Example1
  def my_method
    # some logic
  end
end

class Example2
  def my_other_method
    Example1.find_each(&:my_method)
  end
end

Rspec:

describe Example1 do
  it "should return something" do
    example = Example1.new
    example.my_method.should == something
  end
end

describe Example2 do
  it "should call my_method on Example1" do
    example1 = mock(:example1, :my_method => true)
    example2 = Example2.new

    example1.should_receive(:my_method)
    example2.my_other_method
  end
end

2
2017-12-08 02:15



Ini harus melakukannya:

MyClass.stub(:find_each) {|block|
  block.call
  [one_mock, two_mock]
}

Jika do_stuff_here_on tidak dapat dijangkau secara global, mis. metode instance di some_object, Anda memerlukan beberapa instance_eval untuk mendapatkan cakupan yang tepat untuk blok:

MyClass.stub(:find_each) {|block|
  some_object.instance_eval(&block)
  [one_mock, two_mock]
}

1
2017-11-21 08:47