任何人都知道單元測試斯卡拉演員的好方法嗎?從一般意義上說,我有一個演員接收到一條消息,並會發出其他消息作爲迴應。這是在多個線程上完成的,而一個不正確的參與者可能會發送錯誤的消息或根本沒有消息。我需要一種簡單的方法來創建一個模擬演員,向正在測試的演員發送和接收消息。在這方面有什麼經驗?單元測試斯卡拉演員
回答
由於演員風格的消息傳遞的動態性,嘲諷演員通常沒有任何麻煩。只需創建一個接收所需消息的演員,並且您可以免費回家。你當然需要確保這個模擬演員是傳遞消息的演員,但只要你試圖測試的演員是reentrant,這應該不成問題。
我認爲複雜性取決於幾個因素...
- 如何狀態是演員?
如果它的行爲像一個冪等函數,只是異步的,那麼它應該是一個簡單的事情,嘲笑發送消息的actor,然後檢查它是否收到預期的消息。您可能想要在模擬演員上使用react/receiveWithin,以便在合理的時間段內有響應時您可以失敗而不是掛起。
但是,如果消息不是彼此獨立的,那麼你應該測試它的各種消息序列和預期的結果。
- 被測試的演員會與多少個演員互動?
如果一個actor期望與其他人進行交互,並且它是有狀態的,那麼它應該與幾個參與者發送/接收消息一起測試。由於您可能無法保證消息的到達順序,因此您應該確保排列演員發送消息的順序,或者在演員生成消息時引入隨機暫停並多次運行測試。
我沒有意識到任何測試演員的預先構建的框架,但你可以期待Erlang的靈感。
http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html
我一直想知道如何測試自己的演員。
這是我想出來的,是否有人看到這種方法的問題?
而不是直接發送消息,如果你的演員委託消息發送到一個函數呢?
那麼你的測試可以換出功能與一個跟蹤與該方法被調用的叫做時間和/或參數的個數:
class MyActor extends Actor {
var sendMessage:(Actor, ContactMsg) => Unit = {
(contactActor, msg) => {
Log.trace("real sendMessage called")
contactActor ! msg
}
}
var reactImpl:PartialFunction(Any, Unit) = {
case INCOMING(otherActor1, otherActor2, args) => {
/* logic to test */
if(args){
sendMessage(otherActor1, OUTGOING_1("foo"))
} else {
sendMessage(otherActor2, OUTGOING_2("bar"))
}
}
}
final def act = loop {
react {
reactImpl
}
}
你的測試用例可能包含如下代碼:
// setup the test
var myActor = new MyActor
var target1 = new MyActor
var target2 = new MyActor
var sendMessageCalls:List[(Actor, String)] = Nil
/*
* Create a fake implementation of sendMessage
* that tracks the arguments it was called with
* in the sendMessageCalls list:
*/
myActor.sendMessage = (actor, message) => {
Log.trace("fake sendMessage called")
message match {
case OUTGOING_1(payload) => {
sendMessageCalls = (actor, payload) :: sendMessageCalls
}
case _ => { fail("Unexpected Message sent:"+message) }
}
}
// run the test
myActor.start
myActor.reactImpl(Incoming(target1, target2, true))
// assert the results
assertEquals(1, sendMessageCalls.size)
val(sentActor, sentPayload) = sendMessageCalls(0)
assertSame(target1, sentActor)
assertEquals("foo", sentPayload)
// .. etc.
我試圖在單元測試一個演員(它的工作)。我使用Specs作爲框架。
object ControllerSpec extends Specification {
"ChatController" should{
"add a listener and respond SendFriends" in{
var res = false
val a = actor{}
val mos = {ChatController !? AddListener(a)}
mos match{
case SendFriends => res = true
case _ => res = false
}
res must beTrue
}
這是如何工作的,是通過向單身ChatController發送一個同步調用。 ChatController通過使用回覆()來回應。該響應作爲被調用函數的返回被髮送,該函數被存儲到mos中。然後,將匹配應用於從ChatController發送的案例類。如果結果是所期望的(SendFriends),則將res設置爲true。 資源必須是真實的斷言決定了測試的成敗。那我測試
import ldc.socialirc.model._
import scala.collection.mutable.{HashMap, HashSet}
import scala.actors.Actor
import scala.actors.Actor._
import net.liftweb.util.Helpers._
//Message types
case class AddListener(listener: Actor)
case class RemoveListener(listener: Actor)
case class SendFriends
//Data Types
case class Authority(usr: Actor, role: String)
case class Channel(channelName: String, password: String, creator: String, motd: String, users: HashSet[Authority])
object ChatController extends Actor {
// The Channel List - Shows what actors are in each Chan
val chanList = new HashMap[String, Channel]
// The Actor List - Shows what channels its in
val actorList = new HashMap[Actor, HashSet[String]]
def notifyListeners = {
}
def act = {
loop {
react {
case AddListener(listener: Actor)=>
actorList += listener -> new HashSet[String]
reply(SendFriends)
}
}
}
start //Dont forget to start
}
雖然它沒有完成它並返回Sendfriends案例類如預期
我的演員單。
- 1. 與斯卡拉Akka演員單元測試
- 2. 單身斯卡拉演員?
- 3. 斯卡拉2.8Beta1演員
- 4. 斯卡拉演員左掛
- 5. 斯卡拉遠程演員
- 6. 斯卡拉規格單元測試
- 7. 斯卡拉演員和工作人員
- 8. 將簡單的斯卡拉遠程演員示例移植到阿卡演員
- 9. 斯卡拉演員消息定義
- 10. 斯卡拉遠程演員異常
- 11. 斯卡拉演員 - 最差的做法?
- 12. 使用斯卡拉演員的麻煩
- 13. 在Android上的斯卡拉演員
- 14. 斯卡拉的Guice和Akka演員
- 15. 垃圾回收斯卡拉演員
- 16. 斯卡拉演員智能路由
- 17. 斯卡拉演員和共享狀態
- 18. 斯卡拉演員線程控制
- 19. 在阿卡·斯卡拉演員中使用單身人士
- 20. 斯卡拉/阿卡/吉斯動態注入兒童演員
- 21. 斯卡拉單元測試 - stubbing一個單身人士
- 22. 斯卡拉測試與POST
- 23. 測試XML斯卡拉
- 24. 談到斯卡拉演員阿卡演員:一個實例調用方法在
- 25. 阿卡的演員與斯卡拉的演員模型有什麼區別
- 26. 簡單的斯卡拉演員的問題
- 27. 斯卡拉矩陣反演
- 28. 試圖學習如何使一個簡單的斯卡拉演員
- 29. 斯卡拉測試單元與JSON字符串
- 30. 斯卡拉單元測試更改遷飛資源位置
我認爲丹尼爾是指在上面的測試中用一個像這樣構建的模擬角色替換target1和target2: var target1 = actor {react {case OUTGOING_1(payload){/ * set a flag or append payload .. 。* /}}} 但我的消息通常只包含actor id。有一個目錄actor將消息轉發給id所鍵入的actor。因此,而不是交換sendMessage的實現,我會換出relayMessage。爲了讓代碼更簡單,我把所有這些都留下了。但總的想法是一樣的。 – 2009-07-14 20:17:50