Ravn::Actor::

Testing module

Ravn::Actor testing utilities.

This module contains refinements and other utilities that make unit testing with Actors a bit more deterministic.

It consists primarily of an additional method on the Ravn::Actor class called spawned_as_actor which spawns the Actor class in the normal way an Actor is spawned but with a few of the safeguards removed:

  • Instead of the Actor’s Reference being returned, the instance of the class under test is returned instead. This allows you to expect things of it normally, see its parent and children, etc.

  • If the Actor under test uses StatefulVariables, that setup is done for you and tracked internally. For testing you can access the stateful variables themselves via the normal accessors.

  • Actor re-registration is handled for you.

In addition, the Actor system itself is modified:

  • Concurrent::Actor::Reference is refined to expose the inner actor’s filter_up and filter_down methods directly so you can call inject messages around the actor under test.

  • The safeguards that usually disallow outside callers from accessing the actor’s children are removed, allowing test to expect calls on them by their parent.

In order for these facilities to operate correctly, and to ensure that any spawned actors only run within one example, you’ll need to do two things:

  • Use the refinements in your spec file: using Ravn::Actor::Testing

  • add a cleanup call to your spec’s after( :each ): Ravn::Actor::Testing.cleanup

Example

require 'ravn/actor/testing'

using Ravn::Actor::Testing

describe An::Actor::Class do

    after( :each ) do
        Ravn::Actor::Testing.cleanup
    end

    it "handles incoming messages" do
        message = Ravn::Fixtures.bde_message.instance
        instance = described_class.spawned_as_actor( :the_actor )
        expect( instance ).to receive( :do_the_thing ).with( message )
        instance.on_message( message )
    end

end

Public Class Methods

actors()

The Set of all currently-spawned Actors (mostly used for cleanup)

# File lib/ravn/actor/testing.rb, line 134
singleton_attr_reader :actors
cleanup()

Clean up actors and state after a test run

# File lib/ravn/actor/testing.rb, line 147
def self::cleanup
        self.cleanup_actors
        self.cleanup_state
end
state()

Hash of all Actor StatefulVariable state tables keyed by a random UUID String (mostly used for cleanup)

# File lib/ravn/actor/testing.rb, line 142
singleton_attr_reader :state

Public Instance Methods

spawned_as_actor( name, *args, **kwargs, &block )

Spawn a new instance of the Actor, but return the actual instance instead of the reference.

# File lib/ravn/actor/testing.rb, line 94
def spawned_as_actor( name, *args, **kwargs, &block )
        self.log.warn "Spawning %p as an Actor" % [ self ]

        if self.respond_to?( :stateful_variable )
                id = SecureRandom.uuid
                state = {}
                Ravn::Actor::Testing.state[ id ] = state
                future = Concurrent::Promise.fulfill( state )
                args.unshift( future )
        end

        self.log.debug "Spawning %p with: name=%p, args=%p, kwargs=%p, block=%p" %
                [ self, name, args, kwargs, block ]
        ref = self.spawn!( name, *args, **kwargs, &block )
        Ravn::Actor.register( ref ) unless Ravn::Actor.registered?( name )

        return ref.send( :core ).context
end