lift/framework — pull request #1467 by farmdawgnation (2013-06-29 16:44:57+00:00)
Title: Implementation of a MockSpecializedLiftActor and MockLiftActor

Operating off of the premise of achieving better separation in unit tests, I wanted to implement a MockSpecializedLiftActor and MockLiftActor so that we are able to separate out the testing of if an actor has received a message and the testing of how an actor processes a message. You can read the [mailing list discussion](https://groups.google.com/d/msg/liftweb/V7ixZLhc2TI/nexoHXuCV8kJ) if you want the long form explanation and discussion, but below I'm going to demonstrate the goal in code form.

Given a snippet such that:

```scala
object MyAwesomeSnippet extends MyAwesomeSnippet {
// My awesome actor is a singleton LiftActor.
val myAwesomeActor: LiftActor = MyAwesomeActor
}
trait MyAwesomeSnippet {
def myAwesomeActor: LiftActor

def sendTheActorAMessage {
myAwesomeActor ! SomeMessage
}
}
```

... I want to test that the actor behind `myAwesomeActor` gets `SomeMessage`. Using a real actor, we can't. The mailbox for the actor isn't exposed to us in any way shape or form. So, presently, the only way to check in tests to see if the actor received this message is to check the side-effects of that message being processed (database changes, etc), which isn't very good unit separation.

Ideally, I'd like the ability to write the following test:

```scala
"My Awesome Snippet" should {
"Dispatch the SomeMessage message to the MyAwesomeActor" in {
val myAwesomeSnippetMock = new MyAwesomeSnippet {
val myAwesomeActor = new MockLiftActor()
}

myAwesomeSnippetMock.sendTheActorMessage

myAwesomeSnippetMock.myAwesomeActor.messageCount must_== 1
myAwesomeSnippetMock.myAwesomeActor.hasReceivedMessage_?(SomeMessage) must_== true
}
}
```

By injecting the `MockLiftActor` into the snippet, I'm able to test that the snippet is sending the message to the actor, without worrying over the details of what the *real* actor will do with it. (We can let integration tests worry with that, instead.)