Level 41
Jul 7, 2023
2
Level 5
Mocking traits?
Still very new to mocking and trying to figure out if I can (and indeed if I need to) mock traits?
I have a simple Post model that uses a trait called MediaTrait from Cloudinary that allows me to say $post->attachMedia($image)
I want to write a really simple unit test for the PostController::store() method that simply checks that the Post is correctly saved to the database with the correct fields.
All my assertions pass but I also get two files in cloudinary which I obviously don't want to do every time I test :(
Here is my Store method:
class PostController extends Controller
{
protected $postableType = PostType::GENERIC;
public function store(PostStoreRequest $request): RedirectResponse
{
$validated = $request->validated();
$post = new Post();
$post->message = $validated['message'];
$post->user_id = $request->user()->id;
$post->postable_type = $this->postableType;
$post->save();
if ($validated['images']){
$post->addMedia($validated['images']);
}
$post->refreshCommentCountCache();
return Redirect::route('feed');
}
//
}
My Post model:
class Post extends Model
{
use HasFactory, SoftDeletes;
use MediaTrait;
//
public function addMedia(Array $images)
{
foreach($images as $file){
$this->attachMedia($file);
}
}
}
My test:
class PostStoreMediaTest extends TestCase
{
use RefreshDatabase;
protected User $user;
public function testStoreMethodAddsMediaToPost()
{
//ARRANGE
// Mocking the dependencies and necessary objects
$this->user = User::factory()->create();
$request = $this->partialMock(PostStoreRequest::class, function(MockInterface $mock) {
$mock->shouldReceive('user')->andReturn($this->user);
$mock->shouldReceive('authorized')->andReturn(true);
$mock->shouldReceive('validated')->andReturn([
'message' => 'This is a test post message',
'images' => [ UploadedFile::fake()->image('image1.jpg'),
UploadedFile::fake()->image('image2.jpg')],
]);
});
$media = $this->partialMock(MediaTrait::class, function (MockInterface $mock) {
$mock->shouldReceive('attachMedia')->andReturn(null);
});
//ACT
$controller = new PostController();
$response = $controller->store($request);
// ASSERT
$this->assertDatabaseHas('posts', ['message' => 'This is a test post message']);
$this->assertInstanceOf(RedirectResponse::class, $response);
$this->assertEquals(route('feed'), $response->getTargetUrl());
}
}
Please or to participate in this conversation.