You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

언어와 상관없이 모던한 개발 프레임워크 템플릿들은 유닛테스트를 기본적으로 포함하고 있습니다.

자신이 작성한 서비스 코드에 대한 유닛테스트 작성이 처음이라고 하면 , Nunit/xUnit 적합한 유닛테스트를 먼저 선택을 해야하며 

여기서는 실시간 메시지에대한 유닛테스트기를 어떻게 검증을 할것인가? 실시간 메시지를 조금더 우아하게 테스트할수 있는 방법을 살펴보겠습니다 .

git : https://github.com/psmon/AkkaForNetCore/commit/477a4063a26d8c156f05202eccb3e7d120561d09


준비하기


디렉토리 구조

유닛테스트를 위한 올바른 디렉토리 구조

만약 자신의 프로젝트 소스가 루트에서부터 시작한다고 하면,  뎁스 수정을 권장드립니다.

그러한 디렉토리구조는 이 프로젝트는 앞으로 유닛테스트가 필요없음을 명시하는 방법입니다.


종속성

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Akka.TestKit" Version="1.3.5" />
    <PackageReference Include="Akka.TestKit.NUnit3" Version="1.3.2" />
    <PackageReference Include="nunit" Version="3.11.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.11.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
    <PackageReference Include="Akka" Version="1.3.5" />
  </ItemGroup>

</Project>


여기서 샘플은 Nunit를 선택하였습니다. 


유닛 테스트 작성하기

서비스 코드

using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Event;

namespace AkkaNetCore.Actors
{
    public class CashGateActor : ReceiveActor
    {
        private readonly ILoggingAdapter logger = Context.GetLogger();
        private readonly string id;
        private Random rnd;

        public CashGateActor(int delay)
        {
            rnd = new Random();
            id = Guid.NewGuid().ToString();
            logger.Info($"현금정산게이트 액터 생성:{id} {delay}");

            ReceiveAsync<string>(async msg =>
            {
                //현금정산에 걸리는시간 1~10초, 0일때는 랜덤, 값이 주어질땐 주어진만큼                 
                int auto_delay = delay==0 ? rnd.Next(1000, 10000) : delay;
                await Task.Delay(auto_delay);
                logger.Info($"{msg}-{auto_delay}");
                Sender.Tell($"정산완료 통과하세요");
            });
        }        
    }
}

앞장 성능 확장을 위한 톨게이트 모델에서 현금정산소 Actor를 이용하여 메시지에대한 유닛테스트를 작성해보겠습니다.

메시지를 받으면 지정된 지연시간만큼(for test) 응답을 하는 심플한 코드입니다. -모듈작성때부터 유닛테스트 가능한 방법으로 작성이되면, 유닛테스트 이용과는 별개로 테스트가능한 모듈은 사용성도 높아지게되며 결국 코드품질이 높아지게됩니다.


유닛테스트

테스트 작성

using System;
using Akka.Actor;
using Akka.TestKit;
using Akka.TestKit.NUnit3;
using AkkaNetCore.Actors;
using NUnit.Framework;

namespace AkkaNetCoreTest.Actors
{
    class ActorBaseTest : TestKit
    {
        TestProbe probe;

        [SetUp]
        public void Setup()
        {
            probe = this.CreateTestProbe();
        }
        
        [TestCase(100, 300)]
        public void Actor_should_respond_within_max_allowable_time(int delay, int cutoff)
        {
            var cashGate = Sys.ActorOf(Props.Create(() => new CashGateActor(delay)));
            // sets a maximum allowable time for entire block to finish
            Within(TimeSpan.FromMilliseconds(cutoff), () =>
            {
                cashGate.Tell("정산게이트 통과요청");
                ExpectMsg("정산완료 통과하세요");
            });
        }
    }
}

테스트 수행

이렇게 작성되어진 유닛테스트는 테스트 탐색기를 통해 특정 테스트만 수행할수도 있고 전체를 수행할수도 있습니다.

비동기 처리메시지를 액터와 연동함으로 비동기 메시징에 대한 처리를 유연하게 함과 동시에 심플하고 강력한 방법으로 유닛테스트기를 작성할수가 있습니다.


카프카를 활용한 시스템간 메시징 처리시스템을 구현할경우 AKKA 사용이 필요 없을수도 있습니다.

카프카를 단순한 목적으로 사용하면 상관없겠지만, 우리의 도메인 로직은 카프카의 제공 수준으로만 처리하기엔 부족할수있습니다.

메시지를 한번만전송, 유입량조정 , 유입된 메시지의 유연한 분산처리등 스트림 끝점의 연결은 그에 준하는 스트림 능력을 갖추어야합니다.

이것이 리액티브(https://www.reactive-streams.org/) 가 추구하는 방향이며 

Akka는 Kafka Stream(https://doc.akka.io/docs/alpakka/current/)을 포함하여  Stream을 잘 이해하고 있고, 그에 준하는 능력을 사용할수 있습니다.

  • .net에는 alpakka처럼 공식 인터페이스는 없지만, Akka의 Stream을 활용할수 있습니다.


참고링크

  • No labels