Magento – How to use collection factory model in Unit Test magento 2

collection;magento2modelresource-modelunit tests

I have a custom extension with model with structure like this in database:

+----------------------------------+
|entity_id | customer_id | balance |
+----------------------------------+
|     1    |      3      | 7100000 |
|     2    |      5      | 1250000 |
+----------------------------------+

I usually use my model in __construct function in controller like this:

public function __construct(
.... ,
/Namespace/Module/Model/CreditFactory $credit
... ,
){
  $this->credit = $credit;
}

and i can use to store and retrieve data from my model collection easily like this:

//retrieve Data
$credit = $this->credit->create()->load('1');
$anotherCredit = $this->credit->create()->getCollection()
    ->addFieldToFilter('customer_id','5')->getFirstItem();
$balance = $credit->getBalance();
$anotherBalance = $anotherCredit->getBalance();
//Store Data
$amount = 1000;
$endCreditBalance = $balance - $amount;
$credit->SetBalance(endCreditBalance);
$credit->save();
$endAnotherCreditBalance = $balance + $amount;
$anotherBalance->SetBalance(endAnotherCreditBalance);
$anotherBalance->save();

I tried to create unit test to compared the saved value with the value i want to store like this:

protected function setUp()
{
 $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
 $this->customerCredit = $objectManager->getObject(\Namespace\Module\Model\CreditFactory::class);      
}

public function testSend()
{
 $credit = $this->credit->create()->load('1');
 $anotherCredit = $this->credit->create()->load('2');

 $balance = $credit->getBalance();
 $anotherBalance = $anotherCredit->getBalance(); 
 $amount = 250;
 $endCreditBalance = $balance - $amount;
 $credit->SetBalance(endCreditBalance);
 $credit->save();
 $endAnotherCreditBalance = $balance + $amount;
 $anotherBalance->SetBalance(endAnotherCreditBalance);
 $anotherBalance->save();
 $result = array(
          'credit_balance' => $credit->getBalance(),
          'another_credit_balance' => $anotherCredit->getBalance()
 );
 $expected = array(
          'credit_balance' => $endCreditBalance,
          'another_credit_balance' => $endAnotherCreditBalance
 );
 $this->assertEquals($expected, $result);
}

but i always got an error like this:

Error: Call to a member function load() on null

and i don't know if the rest of the code will work just fine or not

Best Answer

What you are trying to do is actually an integration test and not an unit test. Magento makes an clear distinct in the types of test. With unit tests, all the dependencies of the class you are trying to test are replace with mocks, where all functions return null by default. It is also impossible to access the database as there is no active connection.

With integration tests however you get access to the actual objects and you can access the database.

In your code that is what you actually are trying to do: Testing if the integration between your database and your code is correct.