반응형

BoardsService Test

라라벨 테스트 assert를 통해 테스트코드 작성 실습

테스트코드를 루트\Tests\Unit 폴더에 단위테스트 코드를 작성한 후 아래의 명령어를 터미널에서 실행하면 테스트가 가능

php .\\vendor\\bin\\phpunit

Mocking을 하고싶다면 composer를 통해 설치

composer require --dev mockery/mockery
<?php

namespace Tests\\Unit;

use Tests\\TestCase;
use Illuminate\\Foundation\\Testing\\RefreshDatabase;
use Illuminate\\Support\\Facades\\DB;
use Mockery;
use App\\Http\\Services\\BoardsService;
use stdClass;
use App\\Http\\Dtos\\BoardCommentAddDto;
use App\\Models\\Comment;
use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Support\\Collection;

class UserTest extends TestCase
{

    private $boardsService;

    function setUp(): void
    {
        parent::setUp(); // TestCase의 기본 설정을 불러오기
        $this->boardsService = new BoardsService();
    }

    public function testShow()
    {
        $mock = Mockery::mock('Illuminate\\Database\\Query\\Builder');
        $mock->shouldReceive('join')
        ->once()
        ->with('users', 'boards.user_id', '=', 'users.id')
        ->andReturnSelf();  // 메서드 체이닝을 계속하기 위해 자기 자신을 반환

        $mock->shouldReceive('where')
            ->once()
            ->with('boards.id', 1)
            ->andReturnSelf();  // 메서드 체이닝을 계속하기 위해 자기 자신을 반환

        $mock->shouldReceive('select')
            ->once()
            ->with('boards.*', 'users.name as username')
            ->andReturnSelf();  // 메서드 체이닝을 계속하기 위해 자기 자신을 반환

        $mock->shouldReceive('first')
            ->once()
            ->andReturn((object)['id' => 1, 'username' => 'Test User', 'content' => '글입니다']);  // 가짜 데이터 반환

        DB::shouldReceive('table')
            ->once()
            ->with('boards')
            ->andReturn($mock);

        $result = $this->boardsService->show(1);

        // 결과 검증
        $this->assertInstanceOf(stdClass::class, $result);
        $this->assertEquals(1, $result->id);
        $this->assertEquals('Test User', $result->username);
        $this->assertEquals('글입니다', $result->content);
    }

    public function testCommentAdd()
    {
        $boardCommentAddDto = new BoardCommentAddDto('내용', 1);

        $comment = $this->boardsService->commentAdd($boardCommentAddDto);
        
        $mockComment = new Comment;
        $mockComment->content = '내용';
        $mockComment->board_id = 1;

        $this->assertInstanceOf(Model::class, $comment);
        $this->assertEquals($comment->content, $mockComment->content);
        $this->assertEquals($comment->board_id, $mockComment->board_id);
    }

    public function testCommentsShow()
    {
        $mock = Mockery::mock('Illuminate\\Database\\Query\\Builder');

        $mock->shouldReceive('where')
            ->once()
            ->with('board_id', 1)
            ->andReturnSelf();

        $mock->shouldReceive('select')
            ->once()
            ->with('comments.*')
            ->andReturnSelf();

        $mock->shouldReceive('get')
        ->once()
        ->andReturn(collect([
            (object)['id' => 1, 'content' => '내용', 'board_id' => 1],
            (object)['id' => 2, 'content' => '내용2', 'board_id' => 1]
        ]));

        DB::shouldReceive('table')
            ->once()
            ->with('comments')
            ->andReturn($mock);

        $result = $this->boardsService->commentsShow(1);
        
        $this->assertInstanceOf(Collection::class, $result);
        // $this->assertIsArray($result);
        $this->assertEquals(1, $result[0]->id);
        $this->assertEquals(2, $result[1]->id);
        $this->assertEquals('내용', $result[0]->content);
        $this->assertEquals('내용2', $result[1]->content);
        $this->assertEquals(1, $result[0]->board_id);
        $this->assertEquals(1, $result[1]->board_id);
    }
}

한 메서드안의 assert갯수가 assertions 메서드 각각 tests에 포함

반응형

'공부 > Laravel' 카테고리의 다른 글

Pusher를 활용한 Laravel5.8 + Javascript 소켓통신  (0) 2024.06.20
반응형

라라벨의 브로드캐스팅 기능을 활용해 소켓통신을 실습해보았다

blade템플릿을 사용하면 더 편할텐데 javascript만 사용하는 회사이기에 바닐라js로 시도

적용하는 과정 자체는 몇 단계 없는데 적용하는데 시간을 많이 썼다

csrf토큰을 받아온 후 listen하는 등의 작업을 통해 소켓연결 완료

config/app.php, .env, channels.php, Events/CommentPosted.php, config/broadcasting.php 까지 설정을 완료 후 적절하게 활용하면 된다.

pusher를 composer로 먼저 받기

composer require pusher/pusher-php-server

으로 라라벨에 설치해준 후

위에서 언급한 방식대로 설정해주면 되는데,

app.php

...
'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\\Auth\\AuthServiceProvider::class,
        Illuminate\\Broadcasting\\BroadcastServiceProvider::class, //<<----이친구를 주석해제
        Illuminate\\Bus\\BusServiceProvider::class,
        Illuminate\\Cache\\CacheServiceProvider::class,
        Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider::class,
 ....

.env

BROADCAST_DRIVER=pusher

...

PUSHER_APP_ID=xxxxxxxx
PUSHER_APP_KEY=xxxxxxx
PUSHER_APP_SECRET=xxxxxxxx
PUSHER_APP_CLUSTER=xxxxxx

pusher가입 후

https://dashboard.pusher.com/

Channels에 있는 앱으로 생성 후 나온 값들을 env에 넣어줘야함

channels.php

Broadcast::channel('comment.{boardId}', function ($user, $boardId) {
    // 게시판의 모든 사용자가 이 채널을 들을 수 있도록 설정
    $board = \\App\\Models\\Board::find($boardId);
    if (!$board) return false;

    // 이 예제는 간단하게 모든 사용자에게 접근을 허용합니다.
    return true;
});

구독채널 설정

Events/CommentPosted.php

<?php

namespace App\\Events;

use Illuminate\\Broadcasting\\Channel;
use Illuminate\\Queue\\SerializesModels;
use Illuminate\\Broadcasting\\PrivateChannel;
use Illuminate\\Broadcasting\\PresenceChannel;
use Illuminate\\Foundation\\Events\\Dispatchable;
use Illuminate\\Broadcasting\\InteractsWithSockets;
use Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast;
use App\\Models\\Comment;

class CommentPosted implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $comment;

    public function __construct(Comment $comment)
    {
        $this->comment = $comment;
    }
    
    public function broadcastOn()
    {
        return new PrivateChannel('comment.' . $this->comment->board_id);
    }    

}

ShouldBroadcast를 상속받은 구현체를 만들어서 채널명과 구독방식 등을 정해둘 수 있다.

config/broadcasting.php

...

'connections' => [

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => false,
            ],
        ],
        
...

pusher를 활용해 설정할 때 env()에 담긴 이름은 .env에 지정해둔 설정을 따라가기 때문에 변경할 필요가 없고 통신방식을 확인할 때 useTLS정도만 확인하면 될 것이다. 이번엔 실습을 위해 http일반통신을 하기 위해 false설정

이후 js설정에서

<script src="https://cdn.jsdelivr.net/npm/laravel-echo/dist/echo.iife.min.js"></script>
    <script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
    
    ...

$.ajax({
                url: 'http://localhost:8000/csrf-token',
                type: 'get',
                success: function(data){
                    csrfToken = data.csrfToken;

                    // Pusher를 사용하는 경우의 설정 예제
                    Pusher.logToConsole = true;

                    var pusher = new Pusher('xxxxxxxx', { //key입력
                        cluster: 'xxxxxxx',
                        encrypted: false,
                        auth: {
                            headers: {
                                'X-CSRF-Token': data.csrfToken
                            }
                        }
                    });

                    var echo = new Echo({
                        broadcaster: 'pusher',
                        key: 'xxxxxx',
                        cluster: 'xxxxxxxx',
                        encrypted: false,  // 보안을 위해 true로 설정
                        auth: {
                            headers: {
                                'X-CSRF-TOKEN': data.csrfToken,  // CSRF 토큰 추가
                                'Authorization': 'Bearer ' + localStorage.getItem('accessToken')  // 사용자 토큰 추가
                            }
                        }
                    });
                    // Echo를 사용하여 댓글 채널 구독
                    echo.private('comment.' + globalBoardId)
                        .listen('CommentPosted', (event) => {
                            alert('댓글추가됨');
                    });
                },
                error: function(xhr){

                }
            });

두 Script 라이브러리를 import후에

csrf토큰을 헤더에 추가하여 pusher를 구독 하면 완료!

추가로 csrf토큰을 담지못하면 해당 auth에 문제가 생겨서 구독이 불가능하니 csrf토큰을 발급해서 헤더에 꼭 추가하기!

저는 간단하게 해당 게시글을 구독 후 댓글이 작성될 때마다 alert를 띄우도록 설정했습니다

 

한쪽에서 댓글을 추가 시 양쪽 페이지 모두 listen되어 alert창 팝업

 

Reference : https://laravel.kr/docs/5.8/broadcasting

 
반응형

'공부 > Laravel' 카테고리의 다른 글

Laravel 5.8 TestCode  (0) 2024.06.21

+ Recent posts