Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

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

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


단순하게,작성한  OOP가 반환하는 값을 검사하는 유닛테스트의 수준을 넘어

도메인 로직중에 발생하는 여기서는 실시간 메시지에대한 유닛테스트기를 어떻게 검증을 할것인가? 실시간 메시지를

메시징 유닛테스트를 조금더 우아하게 테스트할수 있는 할수있는 방법을 살펴보겠습니다 .


git Actor Test Source https://github.com/psmon/AkkaForNetCore/commit/477a4063a26d8c156f05202eccb3e7d120561d09tree/master/AkkaNetCoreTest/Actors


준비하기

디렉토리 구조

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

Image Removed

Warning

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

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

종속성

Code Block
themeEmacs
titleNUnit 테스트 프로젝트 종속성
collapsetrue
Code Block
languagec#
themeEmacs
<Project Sdk="Microsoft.NET.Sdk">

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

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

  <ItemGroup>
    <PackageReference Include="Akka.Cluster" Version="1.3.17" />
    <PackageReference Include="Akka.TestKit" Version="1.3.517" />
    <PackageReference Include="Akka.TestKit.NUnit3" Version="1.3.28" />
    <PackageReference Include="nunit" Version="3.1112.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.1115.01" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="1516.94.0" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference<ProjectReference Include="Akka" Version="1.3.5..\AkkaNetCore\AkkaNetCore.csproj" />
  </ItemGroup>

</Project>


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

유닛 테스트 구성은 Nunit Test 와 메시지 유닛 테스트를 위해 Akka.TestKit.Nunit 을 조합하였습니다.


디렉토리 구조

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

Image Added

Warning

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

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

일반적으로 프로젝트가 유닛테스트를 포함하고 싶다고 하면

-프로젝트명

-프젝트트명Test

위와같은 디렉토리 구조를 가지고 됩니다. ( 자바의 경우 Src하위에 UnitTest를 포함하며 계층이 약간 다릅니다.)

유닛 테스트 작성하기

서비스 코드

Code Block
languagec#
themeEmacs
linenumberstrue
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($"정산완료 통과하세요");
            });
        }        
    }
}

...

Code Block
languagec#
themeEmacs
linenumberstrue
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("정산완료 통과하세요");
            });
        }
    }
}

유닛 테스트 작성의 큰흐름은

  • Setup : 객체 테스트에 필요한 의존 요소를 셋팅합니다.  -DI(의존성주입)기능
  • TestCase : 함수단위로 검증 코드를 작성합니다.

테스트 수행

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

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

...

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

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

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

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

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


테스트 컨셉 살펴보기

Image Added

서비스 큐에 값을 넣고, 블락을 시켜 검사하는 방법이 아닌

서비스 큐는, 블락없이 계속 작동을 시키면서 , 테스트 Probe에 쌓인 결과값을 하나씩 꺼내면서 검사를 수행할수 있습니다. 

...



참고링크