title: How to unit-test a reducer with guaranteed randomness? (Redux)
body: <p>I'm attempting to create a react/redux app that isn't the standard "todo". So I went with <a href="http://2048game.com" rel="nofollow noreferrer">2048</a>, it's a fairly fun game that I could fiddle around with.</p>
  
  <p>I've got the game "working" (the game plays by the rules), and now I'd like to retro-actively add some test cases to ensure I don't break anything important down the line (and, y'know, practice).</p>
  
  <p>I have a reducer set up for the board that listens for varying actions:</p>
  
  <pre><code>const Board = (state = 0, action) =&gt; {
      if(state === 0){
          return createBoard();
      }
      switch (action.type) {
          case 'MOVE_UP':
              return move(state, 0);
          case 'MOVE_RIGHT':
              return move(state, 1);
          case 'MOVE_DOWN':
              return move(state, 2);
          case 'MOVE_LEFT':
              return move(state, 3);
          case 'NEW_GAME':
              return createBoard();
          default:
              return state;
      }
  }
  </code></pre>
  
  <p>However the move(board, direction) function does most of the heavy lifting and is where the problem arises:</p>
  
  <pre><code>function move(board, direction){
      //0: up, 1: right, 2: down, 3: left
      var b;
      switch(direction){
          case 0:
              b = mergeBoardUp(board);
              break;
          case 1:
              b = mergeBoardRight(board);
              break;
          case 2:
              b = mergeBoardDown(board);
              break;
          case 3:
              b = mergeBoardLeft(board);
              break;
          default:
              b = board.map(x =&gt; x);
      }
      if(distinctBoard(board, b)){
          b = addNewTile(b);
      }
      return b;
  }
  </code></pre>
  
  <p>My understanding is that reducers should be black-box tested (don't try to pull out and test the "mergeBoardUp" function, test the state after using it). Due to the nature of the game, a new tile is added whenever a valid move is played (<code>if(distinctBoard){addNewTile}</code>).
  I've got a pretty good set of test cases I'd like to implement in terms of testing board rotations and merges, however I can't figure out a way to work around the "random" tile placement.</p>
  
  <p>example test case for reference:</p>
  
  <pre><code>it("MoveUp - simple", () =&gt; {
      var input = [[2,0,0,0],
                  [2,4,8,16],
                  [2,4,0,16],
                  [2,4,8,0]];
  
      var inputHistory = {
          past: [],
          present: input,
          future: []
      };
  
      var expected = [[4,8,16,32],
                      [4,4,0,0],
                      [0,0,0,0],
                      [0,0,0,0]];
  
      var rotatedLeft = Board(inputHistory, MovementButtons.moveUp()).present;
  
      expect(rotatedLeft).toBe(expected);
  })
  </code></pre>
  
  <p>The above fails, because after the valid move, a new tile is placed randomly in the array, causing the "expected" array to always be off by one value.</p>
  
  <p>What would be the appropriate approach for testing in this scenario?
  My instincts are yelling at me to separate the functions I would like to test into a utility file (and test the exported functions from that), but that appears to be an anti-pattern for testing reducers.</p>