How to test Commands and Mediators

eidiot's Avatar

eidiot

25 Dec, 2009 02:56 PM

Hi all,
I have some questions when trying to learn TDD on Robotlegs: How to test Commands and Mediators? I'm writting a simple program which get the current time and show it.

` I have two commands, one is triggered to get the time from the service, the other is to save the date from the service to the model. How can I test these two simple commands? Create mock objects for the service and model and check if the methods are called after the commands are executed?

` I have a mediator who updates the view when the model changed. Have can I test the mediator? Create a mock object for the view and check if the view is updated as the model changed?

May be the two commands are not needed and their works can be moved to the mediator. The question should only be, If I need, and how to test these ( call a service, update a model, etc.), create mock object for the service and model?

I only test models in the past and really want to know if need and how to test commands and mediators (And, if need to test services?). Hope can get your help, thanks very much.

  1. Support Staff 1 Posted by Joel Hooks on 25 Dec, 2009 04:22 PM

    Joel Hooks's Avatar

    With a command, we are interested in answering the question "given a certain input, does it produce the appropriate output". To see this, we'd need to create the event/value object that triggers the command and manually inject it into the command with any dependencies it will need. Then, through a series, run execute to test for various conditions on the "neighbors" that are affected by the command execution.

    For mediators I don't think you'd need a mock view. FlexUnit has the UIImpersonator to act as a stage, so you can add your view class. Then you want to take the same approach, given an event with certain parameters, does the mediator respond accordingly. If the view dispatches an event, does the mediator react as expected (by sending out a system event for instance).

  2. 2 Posted by eidiot on 26 Dec, 2009 03:42 AM

    eidiot's Avatar

    Thanks very much Joel. I know test "what" for them now. But still not sure "how", especially how to "test first" (TDD). I will try it, can you tell me if I'm doing something wrong?

    I have a view which have a text field and a update() method to change its text. Now I want a mediator, call a method of a service to get the time when the view arrives on the stage (onRegister), and update the view when the service complete. (If I should do these in two commands?)

    Step 1. Write a test for the Mediator and then the Mediator class.
    [No question here]

    Step 2. Test if the mediator call the service in onRegister()
    2.1 Create a mock of the service and add a isCalled field.
    2.2 Call the mediator.onRegister();
    2.3 Check if the isCalled of the mock service if true.
    [Question: If I need the mock service here, is there a better way?]

    Step 3. Test if the mediator update the view when the service complete.
    3.1 Dispatch a complete event to the mediator.
    3.2 Check if the mediator updated the view
    [Question: To do this, I public the view's field to check if the mediator changed its value correctly. Should I do this for the test? Or I should create another mock view and keep the view' encapsulation from broken?]

    Here is some of my code:
    .

    //-- TimeMediatorTest --//
    public class TimeMediatorTest {
      private var instance:TimeMediator;
      private var timeServiceMock:TimeSerivceMock;
      [Before]
      public function setUp():void {
        instance = new TimeMediator();
        instance.eventDispatcher = new EventDispatcher();
        var timeView:TimeView = new TimeView();
        instance.timeView = timeView;
        timeServiceMock = new TimeSerivceMock();
        instance.timeService = timeServiceMock;
        instance.onRegister();
      }
      [Test]
      public function testCallServiceOnRegister():void {
        Assert.assertTrue(timeServiceMock.isCalled);
      }
      [Test]
      public function testUpdateViewWhenServiceComplete():void {
        var time:Date = new Date();
        var event:TimeServiceEvent = new TimeServiceEvent(TimeServiceEvent.TIME_RECEIVED, time);
        instance.eventDispatcher.dispatchEvent(event);
        Assert.assertEquals(instance.timeView.timeTf.text, time.toString());
      }
    }
    

    .

    //-- TimeSerivceMock --//
    internal class TimeSerivceMock implements ITimeService {
      public var isCalled:Boolean = false;
      public function getTime():void {
        isCalled = true;
      }
    }
    

    .

    //-- TimeMediator --//
    public class TimeMediator extends Mediator {
      [Inject]
      public var timeView:TimeView;
      [Inject]
      public var timeService:ITimeService;
      override public function onRegister():void {
        eventMap.mapListener(eventDispatcher, TimeServiceEvent.TIME_RECEIVED,
                             timeService_timeReceivedHandler);
        timeService.getTime();
      }
      private function timeService_timeReceivedHandler(event:TimeServiceEvent):void {
        timeView.update(event.time);
      }
    }
    

    Thanks again for your help, and Merry Christmas, if not too late :)

  3. Till Schneidereit closed this discussion on 02 Mar, 2010 12:55 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac