I'm new to unit testing and I'm having issues with testing an API endpoint that creates a new customer.
To be able to create a new customer I need to have an account and subaccount in which to add the new customer. So I first set them up using factories, and then I make a post to the API passing in the $account->id of the account I have just created, and the data needed to create a new customer.
The issue that I'm having is that in API method I have the account type hinted, however when I make the JSON POST request from this test file the account that I'm passing cannot be found.
I don't get a "No query results for model [App\Account]" exception as I would expect if that account didn't exist within the DB. Instead, I get an empty account object, so that when, within that method, I try to access data from the account I get "ErrorException: Trying to get property of non-object" exceptions.
I have tried not using the factories within the test file to create the account, and instead used an account that I know exists in the DB, and I still get the same error.
I have tried using postman to send that same JSON data that I have in the test file to the API endpoint, using the account Id of an account that I know exists, and this correctly creates the new customer.
I have tried removing the DatabaseTransactions trait and checking that the account that the factories are building is created correctly within the database, and it is, and then I've used postman to try and create a new customer within that account and it's been successful.
CreateCustomerTest.php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Customer;
use App\Company;
use App\Account;
use App\SubAccount;
use App\Address;
use App\Agent;
use Carbon\Carbon;
class CreateCustomerTest extends TestCase
{
use WithoutMiddleware;
use DatabaseTransactions;
use DatabaseMigrations;
/** @test */
public function agent_can_create_new_customer()
{
$company = factory(Company::class)->create();
$address = factory(Address::class)->create();
$subaccount = factory(SubAccount::class)->create([
'company_id' => $company->id,
'address_id' => $address->id
]);
$account = factory(Account::class)->create([
'company_id' => $company->id,
'site_id' => $subaccount->id
]);
$agent = Agent::find(2);
$this->actingAs($agent);
//Arrange
$response = $this->json('POST', "/api/account/{$account->id}/customer",[
“foo”=>”bar”
],[ 'X-CSRF-TOKEN' => csrf_token()]);
$this->assertResponseStatus(200);
//Act
$customer = Customer::where("foo", "bar”)->first();
$address = Address::where('id',$customer->address_id)->first();
//Assert
$this->assertEquals( "bar", $customer->foo);
}
}
api.php Route
Route::post('/account/{account}/customer', ['uses'=>'CustomerApiController@addCustomer', 'as'=>'addCustomerEvent']);
CustomerAPIController.php
public function addCustomer(Request $request, Account $account) {
$cus = new Customer();
$company = $account->company()->first();
$validate = Validator::make($request->all(),$cus->validation($company),$cus->messages);
if($validate->fails()) {
return $this->apiResponse($request, ["success"=>false, "fields"=>$validate->errors()->keys(), "errorMessage"=>$validate->errors()->first() ]);
}
...
}
Test exception
CreateCustomerTest::agent_can_create_new_customer
ErrorException: Trying to get property of non-object
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/app/Customer.php:68
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/app/Http/Controllers/CustomerApiController.php:264
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Controller.php:55
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:44
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Route.php:190
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Route.php:144
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Router.php:653
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:104
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Router.php:655
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Router.php:629
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Router.php:607
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:268
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php:53
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:104
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:150
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:117
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:582
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:76
/Users/jamesllewellyn/PhpstormProjects/larascout5.3/scout-5.3/tests/customer/CreateCustomerTest.php:73
Line 68 of Customer.php I am trying to access the $company->id to use in my validation.
Line 264 of CustomerApiController.php is where I call Validator::make passing in the $company
Line 73 of CreateCustomerTest.php is the end of my JSON POST request
Any suggestions would be great as I'm totally stuck with this.
Thanks
James