2014-01-03 5 views
3

У меня есть актер, который напишет файл после получения определенного количества сообщений.Как я могу выполнить единую проверку актера Акка синхронно?

При компиляции Maven выполняет все описанные нами юнит-тесты. Проблема в том, что блок-тест, чтобы проверить, что файл был успешно записан на диск, происходит до того, как актер записывает файл (что он делает правильно).

Я нашел документацию для тестирования Актеры, но все они устарели на несколько лет. Как я могу подождать немного, прежде чем проверять, существует ли файл?

+1

Thread.sleep()? В единичном тесте это нормально, ИМХО. –

+3

Вы прочитали раздел в документах Akka об синхронном модульном тестировании: http://doc.akka.io/docs/akka/2.2.3/scala/testing.html – Ryan

+0

Ed Staub. В модульных тестах почти всегда есть способы избежать Thread.sleep - это считается очень плохой практикой. Я не хочу писать все причины, но я уверен, что вы можете найти его, если хотите. –

ответ

3

Просто суммировать все комментарии и предложения:

  • рефакторинг без актера специального кода для обычных классов и протестировать его с помощью штатных средств (юнит-тесты и т.д.). Это больше подходит для единичного тестирования.
  • Используйте TestActorRef для тестирования одного актера - вы можете управлять событиями синхронно и насыщенно во внутреннее пространство актера. Используйте TestKit, который обеспечивает гораздо больше, включая «специальную» актерскую систему. Это скорее поведенческий подход к тестированию.
  • Используйте документацию here, чтобы узнать больше о том, как работает Akka TestKit, но вкратце вы получаете контроль над своим актером и синхронное выполнение.
+0

Ваш первый вопрос спорный и не помогает достичь цели, насколько я понимаю. Ваш второй пункт не дает конкретного объяснения того, как достичь цели *, конечно * в модульных тестах используется «TestKit». Ваш третий пункт также не объясняет конкретно, как достичь цели. – Stijn

2

Для синхронного тестирования актера, используйте TestProbes (akka.testkit), похожее на это:

import org.scalatest.{FunSuite, BeforeAndAfterAll} 
import org.scalatest.matchers.ShouldMatchers 
import scala.concurrent.duration._ 
import scala.util.Random 
import scala.util.control.NonFatal 
import org.junit.runner.RunWith 
import org.scalatest.junit.JUnitRunner 
import akka.actor.{ActorSystem, ActorRef, Actor, Props} 
import akka.testkit.{TestKit, ImplicitSender, TestProbe} 
import scala.concurrent._ 
import ExecutionContext.Implicits.global 

@RunWith(classOf[JUnitRunner]) 
class Example extends TestKit(ActorSystem("filetest")) 
    with FunSuite 
    with BeforeAndAfterAll 
    with ShouldMatchers 
    with ImplicitSender 
    with Tools { 

    override def afterAll(): Unit = { 
    system.shutdown() 
    } 

    test("Show synchronous actor test") { 
    val tester = TestProbe() 
    val fileActor = system.actorOf(Props(classOf[FileActor]), "case2-primary") 

    tester.send(fileActor, CreateFile(1)) 
    tester.expectMsg(FileCreated(1)) // Will synchronously wait (~500ms in this example) 
    } 
} 

case class CreateFile(id: Long) 
case class FileCreated(id: Long) 

class FileActor extends Actor { 
    def receive = { 
    case CreateFile(id) => { 
     val s = sender 
     createFile(id).map(id => s ! FileCreated(id)) 
    } 
    } 

    def createFile(id: Long): Future[Long] = future { 
    // "Create" the file... 
    Thread.sleep(500) 
    id 
    } 
} 
+0

Что делать, если 'CreateFile' является сообщением о пожаре и забывании? Если вы представите 'FileCreated' для выполнения модульного теста, вам также необходимо изменить вызывающего актера, чтобы получить такое сообщение, или у вас будут мертвые буквы. И изменение реализации для добавления «крючков» для модульных тестов обычно «не выполняется». – Stijn

Смежные вопросы