|
Project Information
|
We are still working on making this library downloadable. For now, see Mock4AS, a simple implementation of a Mock Objects for AS3. IntroductionMockasin is a library that provides an easy way to use Mock Objects for given interfaces in AS3. Mock Objects simulate parts of the behavior of dependent components, and are able to check whether they are used as defined. A Component can be tested in isolation by simulating its dependent components with Mock Objects. Mockasin Benefits
Mockasin Drawbacks (To Do List)
UsageMost parts of a software system do not work in isolation, but collaborate with other parts to get their job done. In a lot of cases, we do not care about using collaborators in unit testing, as we trust these collaborators. If we do care about it, Mock Objects help us to test the unit under test in isolation. Mock Objects replace collaborators of the unit under test. ExampleWe will use the Greeting example to illustrate the basic functionality of Mockasin. The Greeting component says Hello in any language. Greeting uses a Translator component to translate “Hello” from English to the selected language. E.g. greeting.sayHello(“Portuguese”, “Paulo”) should return “Ola Paulo” ITranslator is an interface containing the translate method – parameters from, to and word, which returns the translated word; e.g translate(“English”, “Portuguese”, “Hello”) would return “Ola”. Greeting.as package com.google.mockasin.samples.greeting {
public class Greeting {
private var translator:ITranslator;
public function Greeting(translator:ITranslator) {
this.translator = translator;
}
public function sayHello(language:String, name:String):String {
return translator.translate("English", language, "Hello") + " " + name;
}
}
} ITranslator.as package com.google.mockasin.samples.greeting {
public interface ITranslator {
function translate(from:String, to:String, word:String):String;
}
}At construction time, the Greeting component receives a ITranslator component, a concrete implementation of the ITranslator interface. This simple mechanism is called CDI – Constructor Dependency Injection; basically an instance of the dependent component (some ITranslator implementation) is being injected in the Greeting component at construction time. The following examples assume that you are familiar with the FlexUnit testing framework. Although the tests shown here use FlexUnit in version 0.8.5, you may as well use !ASUnit (release 20071011). The First Mock ObjectWe will now build a test case for the Greeting component and understand the basic functionality of Mockasin. Our first test should check whether the greeting in any language returns the expected result, according to the ITranslator translated “Hello” word. Let’s follow the test code and analyze line by line. (The complete example of our first mock object is provided in the next section.) package com.google.mockasin.samples {
import com.google.mockasin.*;
public class GreetingTest extends TestCase {
public function GreetingTest() {
}The import statement makes the Mockasin functionality available for the current Unit Test code. Make sure your project do include the Mockasin library or source code. public override function setUp():void {
reset();
}The reset() function should be called in between tests to make sure expectations of one test do not interfere with other tests. If the the reset() function is not invoked, expectations will be carried over. Please consider the reset() usage while designing your tests. public function testGreetingInAnyLanguage():void {
// Create the mock.
var mock:MockTranslator = new MockTranslator();An instance of MockTranslator is created. Mockasin gain control over MockTranslator instances by means of MockTranslator extending MockObject. // Set expectations.
expect(mock.translate)
.withArgs("English", "Swedish", "Hello")
.andReturn("Hej");This is how you set expectations on the mock object. In this sample, you are telling Mockasin that translate("English", "Swedish", "Hello") should be invoked for your mock object and it should return "Hej" // Inject the mock.
var myGreeting:Greeting = new Greeting(mock);The Greeting component receives concrete implementation of ITranslator interface as a constructor parameter. Mock is an instance of MockTranslator, which implements ITranslator. // Execute and assert on greeting.
assertEquals("Hej Martin", myGreeting.sayHello("Swedish", "Martin"));
Keep in mind that this test is for the Greeting component. This line is verifying the greeting functionality.
// Verify mock behavior.
verify();
}
}
}The verify() function will verify all expectations set for Mock Objects occurred as specified. In case of a failure, an error – with a meaningful message - is raised and your test will fail. // Inner Class
import com.google.mockasin.MockObject;
import com.google.mockasin.samples.greeting.ITranslator;
class MockTranslator extends MockObject implements ITranslator {
public function translate(from:String, to:String, word:String):String {
return handleCall(arguments, this);
}
}You are required to create a MockTranslator class. In this example, MockTranslator was created as an Inner Class (on the same file) of GreetingTest.as The MockTranslator class must extend from MockObject and implement the ITranslator interface. The interface method implementation should contain return handleCall(arguments, this); Future releases of Mockasin will attempt to remove the need to create the MockTranslator class. The Completed Greeting Examplepackage com.google.mockasin.samples {
import com.google.mockasin.*;
public class GreetingTest extends TestCase {
public function GreetingTest() {
}
public override function setUp():void {
reset();
}
public function testGreetingInAnyLanguage():void {
// Create the mock.
var mock:MockTranslator = new MockTranslator();
// Set expectations.
expect(mock.translate)
.withArgs("English", "Swedish", "Hello")
.andReturn("Hej");
// Inject the mock.
var myGreeting:Greeting = new Greeting(mock);
// Execute and assert on greeting.
assertEquals("Hej Martin", myGreeting.sayHello("Swedish", "Martin"));
// Verify mock behavior.
verify();
}
}
}
// Inner class
import com.google.mockasin.MockObject;
import com.google.mockasin.samples.greeting.ITranslator;
class MockTranslator extends MockObject implements ITranslator {
public function translate(from:String, to:String, word:String):String {
return handleCall(arguments, this);
}
}
|