title: mocking out database queries laravel mockery
body: <p>I am trying to wrap my head around Unit testing with PhpUnit / Mockery / Laravel.
  It's not coming easy. I've been reading dozens of tutorials and still can't apply it in real life scenarios.</p>
  
  <p>I will present a piece of code I would like to test. Can anyone please point me on how to test the method <strong>modifyBasedOnItemCode()</strong> of the class <strong>SoldProductModifier</strong>?</p>
  
  <p>Few words of explanation first:
  I want users to be able to type in the product code (item code) together with quantity, and I want the system to automatically update the product_id as well category_id properties for the SoldProduct model. For this purpose I created the class I now would like to test. </p>
  
  <p>Please also see:
  <a href="http://i.stack.imgur.com/MDH8b.jpg" rel="noreferrer">simplified diagram for my database (only tables related to my question)</a></p>
  
  <p>Now relevant code:</p>
  
  <p><strong>Class to be tested</strong> </p>
  
  <pre>
  
  
      use App\Models\Product;
  
      class SoldProductModifier 
      {
          private $sold_product;
  
          public function __construct(SoldProduct $sold_product) 
          {
              $this->sold_product = $sold_product;
          }
  
          public function modifyBasedOnItemCode($item_code)
          {
              if (! isset($item_code) || $item_code == '')
              {
                  $product = Product::findByItemCode($item_code); 
  
                  if (isset($product) && $product != false)
                  {
                      $this->sold_product->category_id = $product->category->id;
                      $this->sold_product->product_id = $product->id;
                  }
              }
  
              return $this->sold_product;
          }
      }
  
  </pre>
  
  <p><strong>Product Model</strong></p>
  
  <pre>
  
      ...
  
      public static function findByItemCode($item_code) {
          return self::where('item_code', $item_code)->first();
      }
  
      ...
  
  </pre>
  
  <p><strong>My controller referencing SUT</strong></p>
  
  <pre>
  
      ...
  
      $sold_product = new SoldProduct($request->all());
  
      $modifier = new SoldProductModifier($sold_product);
      $sold_product = $modifier->modifyBasedOnItemCode($request->item_code);
  
      $sold_product->save();
  
      ...
  
  </pre>
  
  <p><strong>My test class</strong></p>
  
  <pre>
  
      class SoldProductModifierTest extends TestCase {
  
  
          public function setUp()
          {
              parent::setUp();
  
              $this->soldProductMock = $this->mock('App\Models\SoldProduct');
              $this->productMock = $this->mock('App\Models\Product');
          }
  
          public function tearDown()
          {
              Mockery::close();
          }
  
  
          public function testDoesNotModifyIfItemCodeEmpty()
          {
              $soldProductModifier = new SoldProductModifier($this->soldProductMock);
  
              $modifiedSoldProduct = $soldProductModifier->modifyBasedOnItemCode('');
  
              $this->assertEquals($this->soldProductMock, $modifiedSoldProduct);
          }
  
          public function testModifiesBasedOnItemCode() 
          {
             // how do I test positive case scenario ?
      ...
  
  </pre>
  
  <p>I pasted my first test in case someone thinks it isn't the way it should be done and would be kind to suggest another way of approaching this.</p>
  
  <p><strong>But now to my question:</strong></p>
  
  <p>How do I mock out the call to database here: Product::findByItemCode($item_code) ?</p>
  
  <p>Should I create a $product property in my SoldProductModifier and set it using a setter method created for this purpose, like:</p>
  
  <pre>
  
      public function setProduct(Product $product)
      {
          $this->product = $product;
      }
  
  </pre>
  
  <p>and then add extra line in my controller:</p>
  
  <pre>
  
      ...
  
          $modifier = new SoldProductModifier($sold_product);
          $modifier->setProduct(Product::findByItemCode($item_code)); // --- extra line 
          $sold_product = $modifier->modifyBasedOnItemCode(); // --- parameter removed
  
  
      ...
  
  </pre>
  
  <p>?</p>
  
  <p>I try to keep my controllers as slim as possible, so wanted to avoid that?
  So what is the best way to tackle this kind of situation?</p>
  
  <p>Thank you</p>