RSpec: จะทดสอบได้อย่างไรว่ามีการเรียกเมธอดหรือไม่?


112

เมื่อเขียนการทดสอบ RSpec ฉันพบว่าตัวเองเขียนโค้ดจำนวนมากที่มีลักษณะเช่นนี้เพื่อให้แน่ใจว่ามีการเรียกวิธีการในระหว่างการดำเนินการทดสอบ (เพื่อประโยชน์ในการโต้แย้งสมมติว่าฉันไม่สามารถซักถามสถานะได้จริงๆ ของวัตถุหลังจากการโทรเนื่องจากการดำเนินการที่วิธีการดำเนินการไม่ใช่เรื่องง่ายที่จะเห็นผลของ)

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
    called_bar = false
    subject.stub(:bar).with("an argument I want") { called_bar = true }
    subject.foo
    expect(called_bar).to be_true
  end
end

สิ่งที่ฉันอยากรู้คือ: มีไวยากรณ์ที่ดีกว่านี้หรือไม่? ฉันคิดถึง RSpec สุดเจ๋งที่จะลดโค้ดด้านบนลงเหลือสองสามบรรทัดหรือไม่? should_receiveดูเหมือนว่าควรทำเช่นนี้ แต่อ่านเพิ่มเติมดูเหมือนว่าจะไม่ตรงกับสิ่งที่ทำ


3
ตรวจสอบที่นี่: stackoverflow.com/questions/1328277/…
kddeisz

@Peter Alfvin OP กำลังขอไวยากรณ์อยู่should_receiveดังนั้นฉันคิดว่าคำถามนั้นจะช่วยได้
kddeisz

คำตอบ:


141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end

1
ขออภัยฉันไม่เข้าใจว่ารูปแบบ "ถึง .. รับ (: bar)" นี้ตรวจสอบค่าของ "called_bar" ในตัวอย่างนี้อย่างไร คุณช่วยอธิบายให้ฉันฟังได้ไหม
ecoding5

2
@ ecoding5 เลขที่ called_barมันไม่ได้และไม่ควรตรวจสอบ นั่นเป็นเพียงการตั้งค่าสถานะเพื่อให้แน่ใจว่ามีการเรียกใช้เมธอด แต่เมื่อexpect(...).to receive(...)คุณครอบคลุมสิ่งนั้นแล้ว ชัดเจนและมีความหมายมากขึ้น
wacko

@wacko oooh เข้าใจแล้วขอบคุณสำหรับการล้างข้อมูลนั้น ครั้งแรกผมไม่ได้จับ
ecoding5


37

ด้านล่างควรใช้งานได้

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
     subject.stub(:bar)
     subject.foo
     expect(subject).to have_received(:bar).with("Invalid number of arguments")
  end
end

เอกสารประกอบ: https://github.com/rspec/rspec-mocks#expecting-arguments


ขอบคุณ - ฉันได้รับ "NoMethodError" has_received? - คิดว่าสิ่งนี้อาจเกี่ยวข้องกับ rspec versoins แม้ว่า ฉันพบวิธีแก้ปัญหาอื่นที่เหมาะกับฉัน (วิธีที่ทำเครื่องหมายไว้ด้านบนถูกต้อง)
Mikey Hogarth

@MikeyHogarth คำตอบนี้เป็นการชี้นำhave_received(วิธีการตามความเป็นจริงของ "สายลับ") ไม่ใช่has_receivedซึ่งไม่ใช่ส่วนหนึ่งของ RSpec เวอร์ชันใด ๆ ที่ฉันรู้จัก
Peter Alfvin

2

เพื่อให้สอดคล้องกับไวยากรณ์ RSpec ~> 3.1 และrubocop-rspecตัวเลือกเริ่มต้นสำหรับกฎRSpec/MessageSpiesอย่างสมบูรณ์นี่คือสิ่งที่คุณสามารถทำได้spy:

ความคาดหวังของข้อความทำให้ความคาดหวังของตัวอย่างเป็นจุดเริ่มต้นก่อนที่คุณจะเรียกใช้การทดสอบโค้ดใต้ นักพัฒนาหลายคนชอบใช้รูปแบบการจัดโครงสร้างการกระทำ (หรือกำหนดเมื่อนั้น) ในการจัดโครงสร้างการทดสอบ Spies คือการทดสอบสองประเภททางเลือกที่รองรับรูปแบบนี้โดยให้คุณคาดหวังว่าจะได้รับข้อความหลังจากความจริงโดยใช้ have_received

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("foo@example.com")

# assert.
expect(invitation).to have_received(:deliver).with("foo@example.com")

หากคุณไม่ได้ใช้ rubocop-rspec หรือใช้ตัวเลือกที่ไม่ใช่ค่าเริ่มต้น แน่นอนคุณอาจใช้ RSpec 3 default ด้วยความคาดหวัง

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("foo@example.com")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.