You either have a validation inside of that create method that will assert that you have the required key, or use PHP8 attributes, or even better, use interfaces and avoid arrays.
Setting up types of method parameters for mocks
What I'm trying to unit test here is my create method on my service class. I'm setting up the expectations of what dependencies should be doing. I want to make sure that the types are correct for the repository parameters. What I'm trying to figure out is how to handle the situation where the array passed into create has a key of activated_at. I don't need it to contain a specific value but just contain the key with a string datetime value.
/**
* @test
*/
public function it_can_create_a_user_with_an_activation()
{
$data = [];
$userMock = $this->mock(User::class);
$repositoryMock = $this->mock(UserRepository::class);
$service = new UserService($repositoryMock);
$repositoryMock->expects()->create(\Mockery::type('array'))->once()->andReturns($userMock);
$repositoryMock->expects()->activate($userMock, \Mockery::type('string'))->once()->andReturns($userMock);
$service->create(array_merge(['activated_at' => now()->toDateTimeString()], $data));
}
@jrdavidson You’re right in that a unit test shouldn’t be interacting with things like the database, otherwise you’re not longer testing a unit of your application; you’re testing how that unit interacts with other things, in which case it’s now an integration test. But this doesn’t mean you should write what a feature or integration tests, but then mock everything in oblivion so you can call it a “unit” test.
So, getting back to the problem at hand, I don’t see what it is you’re actually trying to test. If you’re service is instantiated with a repository instance, then that’s what you should be mocking. You then don’t need to mock everything the original repository used because it’s not going to use it any more; the repository is a mock. It has none of its original code contents any more. So instantiate your service with the mock, call your method, and assert the service called the appropriate method was called on your repository mock:
$repository = $this->mock(UserRepository::class, function ($mock) {
$mock
->shouldReceive('someMethod')
->once()
->with($someArg)
->andReturn($someResult);
});
$service = new UserService($repository);
$service->create([
'activated_at' => Carbon::now(),
]);
But I don‘t really know why you’re trying to unit test this. If this is creating a user and you want to check that user has some state, then it makes more sense to make this an integration test than try and unit test it.
Call your methods and assert a row was written to the database with the values you’re expecting.
Please or to participate in this conversation.