In Rspec, I have always understood mocks/stubs to be the same thing.
I still kind of understand them to be the same, except I learned that you can force method to return a specific value; which is great for E2E testing.
For example, if you have a process that takes 5 steps and you want to test it end-to-end ..
class MyClass def multi_step_process result1 = do_step1 result2 = do_step2(result1) result3 = do_step3(result2) result4 = do_step4(result3) do_step5(result4) end def do_step1 def do_step2 ... def do_step5 ... end end
Step 1 is likely some kind of sourcing step. Find me all the records that need to be processed. You can imagine that you want tests on do_step#, but also on my_multistep_process. But how can you do that if step1 changes?
One option is to force some input into result1.
it "verify multi_step_process works e2e" do result1 = stub_step1_result result2 = do_step2(result1) result3 = do_step3(result2) result4 = do_step4(result3) expect(do_step5(result4)).to eq("some expected value") end
This might not always work for you though. In those cases you can use the allow syntax for Rspec. For example, you need to consistenly make sure the logic in your test is the same as is in multi_step_process
it "verify multi_step_process works e2e" do allow(MyClass).to receive(:do_step1).and_return(stub_step1_result) expect(multi_step_process).to eq("some expected value") end
This is super elegant and exactly what you want! No need to remember…
h/t to https://www.rubyguides.com/2018/10/rspec-mocks/ for showing me this.