Test Scenario
We have the following Controller that subscribes to the NewObjectViewController ObjectCreated event. Our task is to check that NewObjectViewController exists and the right handler subscribes to the NewObjectViewController ObjectCreated event.
C#public class CreateLinkedSaleBaseDescendantController : ViewController {
protected override void OnActivated() {
base.OnActivated();
NewObjectViewController standardController = Frame.GetController<NewObjectViewController>();
standardController.ObjectCreated += CreateLinkedSaleBaseDescendantController_ObjectCreated;
}
public void CreateLinkedSaleBaseDescendantController_ObjectCreated(object sender, ObjectCreatedEventArgs e) {
// ...
}
}
Visual BasicPublic Class CreateLinkedSaleBaseDescendantController
Inherits ViewController
Protected Overrides Sub OnActivated()
MyBase.OnActivated()
Dim standardController = Frame.GetController(Of NewObjectViewController)()
AddHandler standardController.ObjectCreated, AddressOf CreateLinkedSaleBaseDescendantController_ObjectCreated
End Sub
Public Sub CreateLinkedSaleBaseDescendantController_ObjectCreated(ByVal sender As Object, ByVal e As ObjectCreatedEventArgs)
'...
End Sub
End Class
Unit Test Implementation
Let's create a test fixture class and a test method:
C#using System;
using System.Reflection;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.SystemModule;
using NUnit.Framework;
using MySolution.Module.Controllers;
namespace MySolution.Tests {
[TestFixture]
public class CreateLinkedSaleBaseDescendantControllerTest {
[Test]
public void Test() {
}
}
Visual BasicImports System.Reflection
Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.SystemModule
Imports NUnit.Framework
Imports MySolution.Module
<TestFixture>
Public Class CreateLinkedSaleBaseDescendantControllerTest
<Test>
Public Sub Test()
End Sub
End Class
Our code uses a Frame instance. Since XafApplication or TemplateContext are not used in our code, we can pass nulls to the Frame constructor.
C#Frame frame = new Frame(null, null);
Visual BasicDim frame As Frame = New Frame(Nothing, Nothing)
Create CreateLinkedSaleBaseDescendantController and NewObjectViewController instances and register them in the Frame.
C#NewObjectViewController newObjectViewController = new NewObjectViewController();
frame.RegisterController(newObjectViewController);
CreateLinkedSaleBaseDescendantController controller = new CreateLinkedSaleBaseDescendantController();
frame.RegisterController(controller);
Visual BasicDim newObjectViewController As NewObjectViewController = New NewObjectViewController()
frame.RegisterController(newObjectViewController)
Dim controller As CreateLinkedSaleBaseDescendantController = New CreateLinkedSaleBaseDescendantController()
frame.RegisterController(controller)
Let's force activation of the controllers:
C#controller.Active.Clear();
controller.Active["Test"] = true;
Visual Basiccontroller.Active.Clear()
controller.Active("Test") = True
Then, we need to check if CreateLinkedSaleBaseDescendantController subscribed to the NewObjectViewController ObjectCreated event. The Moq framework can mock events, but only if they are virtual or implemented in an interface. This is not our case. To verify this, we can use the following helper method that checks if our event handler exists as a method in the NewObjectViewController object.
C#static void VerifyEventSubscription(object objectWithEvent, string eventName, object subscriber, string methodSignature) {
var allBindings = BindingFlags.IgnoreCase | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
var type = objectWithEvent.GetType();
var fieldInfo = type.GetField(eventName, allBindings);
Assert.IsNotNull(fieldInfo);
var eventHandler = fieldInfo.GetValue(objectWithEvent) as Delegate;
Assert.IsNotNull(eventHandler);
Assert.That(subscriber, Is.EqualTo(eventHandler.Target));
Assert.That(methodSignature, Is.EqualTo(eventHandler.Method.ToString()));
}
Visual BasicPrivate Shared Sub VerifyEventSubscription(ByVal objectWithEvent As Object, ByVal eventName As String, ByVal subscriber As Object, ByVal methodSignature As String)
Dim allBindings = BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.Static
Dim type = objectWithEvent.GetType()
Dim fieldInfo = type.GetField(eventName, allBindings)
Assert.IsNotNull(fieldInfo)
Dim eventHandler = TryCast(fieldInfo.GetValue(objectWithEvent), [Delegate])
Assert.IsNotNull(eventHandler)
Assert.That(subscriber, [Is].EqualTo(eventHandler.Target))
Assert.That(methodSignature, [Is].EqualTo(eventHandler.Method.ToString()))
End Sub
where
objectWithEvent
- the object to which event we are subscribing,
eventName
- the subscribed event's name,
subscriber
- the object that subscribes to the event,
methodSignature
- the event handler signature.
Let's call this method to complete our test:
C#string targetMethodName = nameof(CreateLinkedSaleBaseDescendantController.CreateLinkedSaleBaseDescendantController_ObjectCreated);
VerifyEventSubscription(
newObjectViewController,
nameof(newObjectViewController.ObjectCreated),
controller,
$"Void {targetMethodName}({typeof(Object)}, {typeof(ObjectCreatedEventArgs)})"
);
Visual BasicDim targetMethodName As String = NameOf(CreateLinkedSaleBaseDescendantController.CreateLinkedSaleBaseDescendantController_ObjectCreated)
VerifyEventSubscription(
newObjectViewController,
NameOf(newObjectViewController.ObjectCreated),
controller,
$"Void {targetMethodName}({GetType(Object)}, {GetType(ObjectCreatedEventArgs)})"
)
The entire test code will be:
C#[Test]
public void Test() {
Frame frame = new Frame(null, null);
NewObjectViewController newObjectViewController = new NewObjectViewController();
frame.RegisterController(newObjectViewController);
CreateLinkedSaleBaseDescendantController controller = new CreateLinkedSaleBaseDescendantController();
frame.RegisterController(controller);
controller.Active.Clear();
controller.Active["Test"] = true;
string targetMethodName = nameof(CreateLinkedSaleBaseDescendantController.CreateLinkedSaleBaseDescendantController_ObjectCreated);
VerifyEventSubscription(
newObjectViewController,
nameof(newObjectViewController.ObjectCreated),
controller,
$"Void {targetMethodName}({typeof(Object)}, {typeof(ObjectCreatedEventArgs)})"
);
}
Visual Basic<Test>
Public Sub Test()
Dim frame As Frame = New Frame(Nothing, Nothing)
Dim newObjectViewController As NewObjectViewController = New NewObjectViewController()
frame.RegisterController(newObjectViewController)
Dim controller As CreateLinkedSaleBaseDescendantController = New CreateLinkedSaleBaseDescendantController()
frame.RegisterController(controller)
controller.Active.Clear()
controller.Active("Test") = True
Dim targetMethodName As String = NameOf(CreateLinkedSaleBaseDescendantController.CreateLinkedSaleBaseDescendantController_ObjectCreated)
VerifyEventSubscription(
newObjectViewController,
NameOf(newObjectViewController.ObjectCreated),
controller,
$"Void {targetMethodName}({GetType(Object)}, {GetType(ObjectCreatedEventArgs)})"
)
End Sub
See Also:
This series contains the following articles:
- How to write unit tests for XAF Actions, Controllers, and other custom UI logic
- How to unit test Action's enabled/disabled state based on user permissions
- How to unit test whether object property changes via Actions were successfully committed
- How to unit test object queries by criteria and Detail View creation
- How to unit test event handlers in Controllers (current)
- How to unit test New Action's custom business logic based on parent and nested Views
- How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View
- How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in Detail View
- How to unit test localized strings from CaptionHelper (Approach 1)
- How to unit test localized strings from CaptionHelper (Approach 2)
- How to unit test custom logic in XAF/XPO business classes