var command:SaveRecipeCommand = new SaveRecipeCommand(); command.dispatcher = new EventDispatcher(); command.service = new FakeRecipeService(); command.event = new SaveRecipeEvent(recipe); events.from(command.dispatcher).hasType(RecipeSavedEvent.SAVED); command.execute(); } public class FakeRecipeService extends FakeService implements IRecipeService { public function save(recipe:Recipe):AsyncToken { var savedRecipe:Recipe = recipe.clone(); savedRecipe.reset(); return respondWithAsyncResult(new AsyncToken(), savedRecipe); ! } }
command.dispatcher = new EventDispatcher(); command.service = new FakeRecipeService(); command.event = new RetrieveRecipeListEvent(); events.from(command.dispatcher) .hasType(RecipeListRetrievedEvent.RETRIEVED) .calls(function(event:RecipeListRetrievedEvent):void { assertThat(event.recipeList, instanceOf(RecipeList)); }); command.execute(); } public class FakeRecipeService extends FakeService implements IRecipeService { public function retrieveList(options:RecipeListOptions):Promise { var recipeList:RecipeList = new RecipeList(); var recipe:Recipe; for (var i:int = 0, n:int = 5; i < n; i++) { recipe = new Recipe(); // many lines of setting up fake data for this recipe. recipeList.add(recipe); } return respondWithAsyncResult(new AsyncToken(), recipeList); ! } }
= new ModifiedRecipe(); assertThat(presenter.saveEnabled, isTrue()); } [Test] public function unmodified_recipe_should_disable_saving():void { presenter = new EditRecipePresenter(); presenter.recipe = new UnmodifiedRecipe(); assertThat(presenter.saveEnabled, isFalse()); } internal class ModifiedRecipeStub extends Recipe { override public function isModified():Boolean { return true; } } internal class UnmodifiedRecipeStub extends Recipe { override public function isModified():Boolean { return false; } }
var service:MockRecipeService = new MockRecipeService(); service.saveCallback = function(recipe:Recipe):void { var deferred:Deferred = new Deferred(); deferred.reject(); return deferred.promise; } var command:SaveRecipeCommand = new SaveRecipeCommand(); command.dispatcher = new EventDispatcher(); command.service = service; command.event = new SaveRecipeEvent(recipe); events.from(command.dispatcher).hasType(RecipeSaveErrorEvent.ERROR); command.execute(); } internal class MockRecipeService implements IRecipeService { public var saveCallback:Function; public function save(recipe:Recipe):Promise { return saveCallback(recipe); } }
{ dishwasher.start(); } } class AutomaticDishwasher { public function start():void { door.lock(); hotwater.on(); timer.start(); // ... } } class MumsPartyKitchen implements IKitchen { public function cleanDishes():void { // noop, we're using paper plates. } }
class CommercialKitchen { public function CommercialKitchen(dishwasher:IDishwasher) {} public function cleanDishes():void { dishwasher.start(); } } public interface IDishwasher { function start():void; } public class AutomaticDishwasher { public function AutomaticDishwasher( timer:ITimer, waterSupply:IWaterSupply, electricitySupply:IElectricitySupply) {} public function start():void { timer.start(); } }
Kitchen are blackboxes. var chef:Chef = new Chef(); var kitchenSpy:KitchenSpy = new KitchenSpy(); var meal:Meal = chef.prepareMeal(kitchen); trace("which ingredients did the chef use?", ObjectUtil.toString(kitchenSpy.ingredientsUsed)); } public class KitchenSpy extends Kitchen { public var ingredientsUsed:Array = []; override public function findIngredient(name:String):Ingredient { var ingredient:Ingredient = super.findIngredient(name); ingredientsUsed.push({ name: name, ingredient: ingredient }); return ingredient; } }
PreparingWithFlexUnit { [Rule] public var mocks:MockolateRule = new MockolateRule(); [Mock] public var service:IRecipeService; [Mock] public var dispatcher:IEventDispatcher; private var command:SaveRecipeCommand; [Before] public function setup():void { command = new SaveRecipeCommand(); command.dispatcher = dispatcher; command.service = service; } } }
[Rule] public var mocks:MockolateRule = new MockolateRule(); [Mock] public var aNiceRecipeService:IRecipeService; [Mock(type="nice")] public var anotherNiceRecipeService:IRecipeService; [Mock(type="strict")] public var aVeryStrictChef:Chef; [Mock(type="partial")] public var aPartialKitchen:Kitchen; [Test] public function in_other_cases():void { aNiceRecipeService = nice(IRecipeService); anotherNiceRecipeService = nice(IRecipeService); aVeryStrictChef = strict(Chef); aPartialKitchen = partial(Kitchen); } } }
[Test] public function attempting_to_create_an_unprepared_class():void { var friend:Friend = nice(Friend); } } } ArgumentError: No proxy class prepared for mockolate.examples::Friend
"Nigella Lawson"); var kitchen:Kitchen = nice(Kitchen); var meal:Meal = chef.prepareMeal(kitchen); assertThat("expecting a delicious Meal", meal, instanceOf(Meal)); } Error: expecting a delicious Meal Expected: an instance of mockolate.examples::Meal but: was null
"Gordon Ramsey"); var kitchen:Kitchen = nice(Kitchen); var meal:Meal = chef.prepareMeal(kitchen); assertThat("expecting a delicious Meal", meal, instanceOf(Meal)); } Error: No Expectation defined for mockolate.examples::Chef(Gordon Ramsey).prepareMeal(< [object Kitchen76D845B3B7C233645BB7006A92386336F7A5E215]>)
function unknown_invocation_with_partial_mock_object_of_interface():void { var chef:IChef = partial(IChef, "Heston Blumenthal"); var kitchen:Kitchen = nice(Kitchen); var meal:Meal = chef.prepareMeal(kitchen); assertThat("expecting a delicious Meal", meal, instanceOf(Meal)); } Error: Cannot proceed on method because it is an interface method: mockolate.generated:IChefBC4E5F6D949F4FB02ED3B5E8C6471E5AA3B578C9/prepareMeal
new Meal("Something Delicious"); } } [Test] public function unknown_invocation_with_partial_mock_object():void { var chef:Chef = partial(Chef, "Heston Blumenthal"); var kitchen:Kitchen = nice(Kitchen); var meal:Meal = chef.prepareMeal(kitchen); assertThat("expecting a delicious Meal", meal, instanceOf(Meal)); }
new Meal("Scrabbled Eggs"); } } [Test] public function verify_with_unmet_expectation():void { var chef:Chef = new Chef(); var kitchen:Kitchen = nice(Kitchen); expect( kitchen.prepare(arg(Recipe), arg(chef)) ).once(); var meal:Meal = chef.prepareMeal(kitchen); verify(kitchen); } // 1 unmet Expectation mockolate.example::Kitchen#prepare(<[class Recipe]>,<[object Chef] >); should to be invoked <1> times but was invoked <0> times
var chef:Chef = new Chef(); var meal:Meal = chef.prepareMeal(kitchen); expect( kitchen.prepare(arg(Recipe), arg(chef)) ).once(); var meal:Meal = chef.prepareMeal(kitchen); } // no error
} // 1 unmet Expectation mockolate.examples::Flavour(flavour)#name; should to be invoked <1> times but was invoked <0> times. [Test] public function using_allow():void { allow( flavour.name ).returns( "Chocolate" ).once(); } // No Error. [Test] public function using_mock():void { mock( flavour ).getter( "name" ).returns( "Chocolate" ).once(); } // 1 unmet Expectation mockolate.examples::Flavour(flavour)#name; should to be invoked <1> times but was invoked <0> times. [Test] public function using_stub():void { stub( flavour ).getter( "name" ).returns( "Chocolate" ).once(); } // No Error.
function returning_a_value():void { var order:CoffeeOrder = new CoffeeOrder(); expect( coffeeMachine.make(order) ) .returns( new FlatWhite() ); assertThat(coffeeMachine.make(order), instanceOf(FlatWhite)); assertThat(coffeeMachine.make(order), instanceOf(FlatWhite)); } [Test] public function returning_a_sequence_of_values():void { var order:CoffeeOrder = new CoffeeOrder(); expect( coffeeMachine.make(order) ) .returns( new Latte(), new Cappucino() ); assertThat(coffeeMachine.make(order), instanceOf(Latte)); assertThat(coffeeMachine.make(order), instanceOf(Cappucino)); assertThat(coffeeMachine.make(order), instanceOf(Cappucino)); }
AsyncToken(); var result:Array = [new Recipe(), new Recipe()]; expect( recipeService ).returns(token).answers(withResult(token, result)); } public function withResult(token:AsyncToken, result:*):Answer { return new ResultAnswer(token, new ResultEvent(ResultEvent.RESULT, false, false, result, token)); } public class ResultAnswer { public function invoke(invocation:Invocation):* { setTimeout(applyResult, _delay); return undefined; } protected function applyResult():void { _token.mx_internal::applyResult(_resultEvent); } }
CoffeeOrder(); expect( coffeeMachine.make(order) ) .callsWithArguments(function(receivedOrder:CoffeeOrder):void { trace('CoffeeMachine.make(order) was called with ', receivedOrder); }); }
{ if (!value) throw new ArgumentError("ErrorProne#accept requires a value"); } } [Test] public function spying_on_thrown_errors():void { var errorProne:ErrorProne = partial(ErrorProne, "errorProne"); var errorSpy:Spy = spy(errorProne.accept(arg(anything()))); try { errorProne.accept(false); } catch (e:Error) { } assertThat(errorSpy.threw(ArgumentError)); }
} [Mock] public var recipeModel:IRecipeModel; [Test] public function stub_queries():void { var recipes:RecipeList = new RecipeList(); recipes.add(new Recipe()); recipes.add(new Recipe()); recipes.add(new Recipe()); allow( recipeModel.getRecipes() ).returns( recipes ); }
} [Mock] public var recipeSerivce:IRecipeService; [Test] public function mock_actions():void { var token:AsyncToken = new AsyncToken(); expect( recipeService.retrieveList() ).returns( token ); }