title: How does RSpec allowing and expecting producing unexpected results for multiple calls
body: <p>I'm trying to write a test to prevent you from doing the same thing twice (in this case, playing on the same square twice in tictactoe), but RSpec syntax is confusing me and I can't see a solution in their docs. I've tried a few approaches with no success, which have made me realise I don't understand RSpec syntax as well as I thought.</p>
  <p>Because the tests are for a recursive method, a lot of the errors aren't as descriptive as I'd like since they cause the program to crash, which is making it hard to isolate the problem.</p>
  <p>The method I'm trying to test/create will initially look something like this:</p>
  <blockquote>
  <p>def your_turn</p>
  <pre><code>your_turn unless play_on(square_at(get_row, get_square))
  </code></pre>
  <p>end</p>
  </blockquote>
  <p>(play_on returns nil if it doesn't successfully place a marker)</p>
  <p>In this case I'm testing a module for which, your_turn, get_row and get_square are that module's methods, but play_on and square_at are methods from the class into which it's getting integrated, so I'm stubbing where necessary (ditto the get methods, since I don't want to get prompted by RSpec).</p>
  <p>The first test I tried was this:</p>
  <blockquote>
  <p>it 'repeats the process if a player can't play on that square' do</p>
  <pre><code>allow(human).to receive(:play_on).and_return(nil, :square)
  
  expect(human).to receive(:your_turn).twice
  
  human.your_turn
  </code></pre>
  <p>end</p>
  </blockquote>
  <p>The test fails, and says it was only received once. The way I expected this to unfold was on the initial your_turn call, RSpec would stub play_on, return nil, setting off the unless statement and repeating the your_turn call - after which it would return a symbol and prevent any further recursion. What have I misunderstood?</p>
  <p>After that effort, I came up with a monstrosity that seems to work, but I'm not entirely sure why:</p>
  <blockquote>
  <p>allow(human).to receive(:get_row).and_return(1,2)</p>
  <p>allow(human).to receive(:get_square).and_return(2,2)</p>
  <p>allow(human).to receive(:square_at).with(1, 2).and_return(:nil)</p>
  <p>allow(human).to receive(:square_at).with(2, 2).and_return(:square)</p>
  <p>allow(human).to receive(:play_on).with(:square).and_return(:square)</p>
  <p>expect(human).to receive(:play_on).twice</p>
  <p>human.your_turn</p>
  </blockquote>
  <p>The trouble here (other than this being ugly) is I got it to work more through brute force than understanding, and there's a couple of things I'm not sure of:</p>
  <ul>
  <li>Why can I not remove eg the first two lines without the prompt returning to RSpec? Since on the third and fourth lines I'm stubbing the method square_at, which would call the get_ methods, why are they still being called?</li>
  <li>Similarly, the fifth line third and fourth line seemed to cover the third and fourth, but I initially had the last 'allow' return(nil, :square), expecting that to work. That ended up calling your_turn three times where I was expecting two, so I removed the nil and it passed. The way I parse it, without the nil, play_on will return :square immediately, so the unless logic won't be triggered and the method will terminate. Again, what have I misunderstood?</li>
  <li>Is there a dryer way of dealing with the two 'square_at' allowing lines?</li>
  </ul>
  <p>Thanks all,</p>
  <p>Sasha</p>