This topic provides step-by step instructions on how to test an XAF application. A custom Controller that provides the Postpone Action is implemented in this example. Then, this Action's functionality will be tested via the EasyTest functional testing and NUnit unit testing frameworks.

Note
Mobile applications do not support the EasyTest functional testing.
Implement a Custom Action
Create a new XAF application solution named PostponeControllerTest. The custom Controller will perform an Action over Task business objects. The sample Task business class exposes two properties - Description and DueDate.
[DefaultClassOptions]
public class Task : BaseObject {
public Task(Session session) : base(session) { }
public string Description {
get { return GetPropertyValue<string>(nameof(Description)); }
set { SetPropertyValue<string>(nameof(Description), value); }
}
public DateTime DueDate {
get { return GetPropertyValue<DateTime>(nameof(DueDate)); }
set { SetPropertyValue<DateTime>(nameof(DueDate), value); }
}
}
<DefaultClassOptions> _
Public Class Task
Inherits BaseObject
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
Public Property Description() As String
Get
Return GetPropertyValue(Of String)(NameOf(Description))
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)(NameOf(Description), value)
End Set
End Property
Public Property DueDate() As DateTime
Get
Return GetPropertyValue(Of DateTime)(NameOf(DueDate))
End Get
Set(ByVal value As DateTime)
SetPropertyValue(Of DateTime)(NameOf(DueDate), value)
End Set
End Property
End Class
The custom Controller is targeted for List Views and contains the Postpone Action. This Action processes the selected objects in a Task List View. The Action adds one day to the objects' DueDate property values.
public class PostponeController : ViewController {
private SimpleAction postpone;
public PostponeController() {
TargetObjectType = typeof(Task);
postpone = new SimpleAction(this, "Postpone", "Edit");
postpone.Execute += new SimpleActionExecuteEventHandler(Postpone_Execute);
}
void Postpone_Execute(object sender, SimpleActionExecuteEventArgs e) {
foreach (object selectedObject in View.SelectedObjects) {
Task selectedTask = (Task)selectedObject;
if (selectedTask.DueDate == DateTime.MinValue) {
selectedTask.DueDate = DateTime.Today;
}
selectedTask.DueDate = selectedTask.DueDate.AddDays(1);
}
}
public SimpleAction Postpone {
get { return postpone; }
}
}
Public Class PostponeController
Inherits ViewController
Private _postpone As SimpleAction
Public Sub New()
TargetObjectType = GetType(Task)
_postpone = New SimpleAction(Me, "Postpone", "Edit")
AddHandler _postpone.Execute, AddressOf Postpone_Execute
End Sub
Private Sub Postpone_Execute(ByVal sender As Object, ByVal e As SimpleActionExecuteEventArgs)
For Each selectedObject As Object In View.SelectedObjects
Dim selectedTask As Task = CType(selectedObject, Task)
If selectedTask.DueDate = DateTime.MinValue Then
selectedTask.DueDate = DateTime.Today
End If
selectedTask.DueDate = selectedTask.DueDate.AddDays(1)
Next selectedObject
End Sub
Public ReadOnly Property Postpone() As SimpleAction
Get
Return _postpone
End Get
End Property
End Class
Functional Tests
This section describes a way of creating an EasyTest script that ensures that the implemented Postpone Action works as expected. The test will work for both Windows Forms and ASP.NET Web applications.
In Solution Explorer, navigate to the module project. Right-click the FunctionalTests folder and select Add | New Item.

In the Add New Item dialog, select Text File and enter "PostponeControllerTest.ets" as the new file's name. When the Visual Studio text editor is invoked, enter the following code.
#DropDB PostponeControllerTestEasyTest
#Application PostponeControllerTest.Win
#Application PostponeControllerTest.Web
*Action New(Task)
*FillForm
Description = Test Task One
Due Date = 06/06/2011
*Action Save and New
*FillForm
Description = Test Task Two
Due Date = 07/07/2011
*Action Save and Close
*Action Navigation(Task)
*SelectRecords
Columns = Description
Row = Test Task One
Row = Test Task Two
*Action Postpone
*CheckTable
Columns = 'Due Date'
Row = 6/7/2011
Row = 7/8/2011
This script creates two Task objects, selects them in the List View and executes the Postpone Action. After that, the script ensures that the test objects' DueDate property values change as expected. For detailed information on the EasyTest command syntax, refer to the EasyTest Script Reference topic.
Note
By default, the FunctionalTests folder contains the Sample.ets script. You can use it as a starting point when creating tests. If you do not need this file, you can delete it. Another file, initially located in the FunctionalTests folder, is Config.xml. This file specifies the EasyTest configuration settings and should not be deleted.
Save the test script. Right-click this file in Solution Explorer and select Run:

The test will first be executed in Windows Forms, and then in the ASP.NET application (this is specified by the second and third commands of the test script). You will then see the following output, indicating that all tests passed successfully.

Unit Tests
This section describes a way of creating a unit test that ensures that the implemented Postpone Action works as expected.
- In the module project, add a reference to the nunit.framework assembly.
Implement the following simple TestApplication class, since it is required by the test above.
using DevExpress.ExpressApp.Layout;
// ...
class TestApplication : XafApplication {
protected override LayoutManager CreateLayoutManagerCore(bool simple) {
return null;
}
}
Imports DevExpress.ExpressApp.Layout
' ...
Friend Class TestApplication
Inherits XafApplication
Protected Overrides Function CreateLayoutManagerCore( _
ByVal simple As Boolean) As LayoutManager
Return Nothing
End Function
End Class
We cannot instantiate the XafApplication class itself, as it is abstract. So, we create a lightweight descendant. The use of a built-in XafApplication descendant (e.g., WinApplication) is possible, but not recommended in this scenario, as the test will take more time to start.
Add the following test class to the module project.
using NUnit.Framework;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Xpo;
// ...
[TestFixture]
public class PostponeControllerUnitTest {
IObjectSpace objectSpace;
PostponeController controller;
TestApplication application;
[SetUp]
public void SetUp() {
XPObjectSpaceProvider objectSpaceProvider =
new XPObjectSpaceProvider(new MemoryDataStoreProvider());
application = new TestApplication();
ModuleBase testModule = new ModuleBase();
testModule.AdditionalExportedTypes.Add(typeof(Task));
application.Modules.Add(testModule);
application.Setup("TestApplication", objectSpaceProvider);
objectSpace = objectSpaceProvider.CreateObjectSpace();
controller = new PostponeController();
}
[Test]
public void TestPostponeActionDueDateUnspecified() {
Task task = objectSpace.CreateObject<Task>();
controller.SetView(application.CreateDetailView(objectSpace, task));
controller.Postpone.DoExecute();
Assert.AreEqual(task.DueDate, DateTime.Today.AddDays(1));
}
[Test]
public void TestPostponeActionDueDateSpecified() {
Task task = objectSpace.CreateObject<Task>();
task.DueDate = new DateTime(2011, 6, 6);
controller.SetView(application.CreateDetailView(objectSpace, task));
controller.Postpone.DoExecute();
Assert.AreEqual(task.DueDate, new DateTime(2011, 6, 7));
}
}
Imports NUnit.Framework
Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.Xpo
' ...
<TestFixture> _
Public Class PostponeControllerUnitTest
Private objectSpace As IObjectSpace
Private controller As PostponeController
Private application As TestApplication
<SetUp> _
Public Sub SetUp()
Dim objectSpaceProvider As _
New XPObjectSpaceProvider(New MemoryDataStoreProvider())
application = New TestApplication()
Dim testModule As New ModuleBase()
testModule.AdditionalExportedTypes.Add(GetType(Task))
application.Modules.Add(testModule)
application.Setup("TestApplication", objectSpaceProvider)
objectSpace = objectSpaceProvider.CreateObjectSpace()
controller = New PostponeController()
End Sub
<Test> _
Public Sub TestPostponeActionDueDateUnspecified()
Dim task As Task = objectSpace.CreateObject(Of Task)()
controller.SetView(application.CreateDetailView(objectSpace, task))
controller.Postpone.DoExecute()
Assert.AreEqual(task.DueDate, DateTime.Today.AddDays(1))
End Sub
<Test> _
Public Sub TestPostponeActionDueDateSpecified()
Dim task As Task = objectSpace.CreateObject(Of Task)()
task.DueDate = New DateTime(2011, 6, 6)
controller.SetView(application.CreateDetailView(objectSpace, task))
controller.Postpone.DoExecute()
Assert.AreEqual(task.DueDate, New DateTime(2011, 6, 7))
End Sub
End Class
In this test, we instantiate an application and ObjectSpaceProvider. Then, required modules and business objects are registered. After that, it is possible to create a Controller to be tested and set a View to it. To execute an Action in a test, the SimpleAction.DoExecute method is used. Note that the Postpone Action is exposed by the Controller's public property to allow for accessing the Action externally.
Note
You can enclose the test fixture code in #ifdef DEBUG and #endif statements to exclude tests from the release version of your application.
Build the module project, and open the output assembly in the NUnit GUI Runner (nunit.exe). Then, click Run to see the results.

If you want to test an action that is available in a List View, or in a Detail View containing nested List View, then you need a TestApplication class that implements the CreateListEditorCore virtual method. The reason is that when the XafApplication.CreateListView method is executed, the List Editor is instantiated. As there are no built-in platform-independent List Editors in XAF, you should implement the fake List Editor for testing purposes and return an instance of this List Editor in the overridden CreateListEditorCore method.
using DevExpress.ExpressApp.Layout;
using DevExpress.ExpressApp.Editors;
// ...
class TestApplication : XafApplication {
protected override LayoutManager CreateLayoutManagerCore(bool simple) {
return null;
}
protected override ListEditor CreateListEditorCore(
IModelListView modelListView, CollectionSourceBase collectionSource) {
return new TestListEditor(modelListView);
}
}
internal class TestListEditor : ListEditor {
public TestListEditor(IModelListView modelListView) {
SetModel(modelListView);
}
protected override object CreateControlsCore() {
throw new NotImplementedException();
}
protected override void AssignDataSourceToControl(object dataSource) { }
public override void Refresh() { }
public override System.Collections.IList GetSelectedObjects() {
return new List<object>();
}
public override SelectionType SelectionType {
get { return SelectionType.MultipleSelection; }
}
public override DevExpress.ExpressApp.Templates.IContextMenuTemplate ContextMenuTemplate {
get { return null; }
}
}
Imports DevExpress.ExpressApp.Layout
Imports DevExpress.ExpressApp.Editors
' ...
Friend Class TestApplication
Inherits XafApplication
Protected Overrides Function CreateLayoutManagerCore(ByVal simple As Boolean) As LayoutManager
Return Nothing
End Function
Protected Overrides Function CreateListEditorCore( _
ByVal modelListView As IModelListView, ByVal collectionSource As CollectionSourceBase) As ListEditor
Return New TestListEditor(modelListView)
End Function
End Class
Friend Class TestListEditor
Inherits ListEditor
Private Function MyTestListEditor(ByVal modelListView As IModelListView) As [Public]
SetModel(modelListView)
End Function
Protected Overrides Function CreateControlsCore() As Object
Throw New NotImplementedException()
End Function
Protected Overrides Sub AssignDataSourceToControl(ByVal dataSource As Object)
End Sub
Public Overrides Sub Refresh()
End Sub
Public Overrides Function GetSelectedObjects() As System.Collections.IList
Return New List(Of Object)()
End Function
Public Overrides ReadOnly Property SelectionType() As SelectionType
Get
Return SelectionType.MultipleSelection
End Get
End Property
Public Overrides ReadOnly Property ContextMenuTemplate() _
As DevExpress.ExpressApp.Templates.IContextMenuTemplate
Get
Return Nothing
End Get
End Property
End Class
With the TestApplication implementation illustrated above, you can use the XafApplication.CreateListView method in your unit tests.
See Also