KB Article T853927
Visible to All Users

How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in Detail View

Test Scenario
This case is similar to the one described in the How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View article. The difference is that we need to ensure that an Action is correctly enabled/disabled in a Detail View.

Unit Test Implementation
Let's create a test similar to the one described in the How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View article, but for a Detail View. We need to change it to create a DetailView instance that requires a single object and mock the IObjectSpace.Contains method for the reason described in the How to unit test object queries by criteria and Detail View creation article.

C#
[Test] [TestCase(Priority.High, true)] [TestCase(Priority.Low, false)] public void ActionsInDetailViewTest(Priority priority, bool result) { ActionsCriteriaViewController actionsCriteriaViewController = new ActionsCriteriaViewController(); ViewController testedController = new ViewController(); SimpleAction testedAction = new SimpleAction(testedController, "High Priority", string.Empty); testedAction.TargetObjectsCriteria = "Priority = 2"; DemoTask task = new DemoTask(Session.DefaultSession); task.Priority = priority; var objectSpaceMock = new Mock<IObjectSpace>(); objectSpaceMock.Setup(os => os.Contains(It.IsAny<object>())).Returns(true); objectSpaceMock.Setup(os => os.GetEvaluatorContextDescriptor(typeof(DemoTask))).Returns(new EvaluatorContextDescriptorDefault(typeof(DemoTask))); var applicationMock = new Mock<XafApplication>(); Frame frame = new Frame(applicationMock.Object, TemplateContext.View, actionsCriteriaViewController, testedController); frame.SetView(new DetailView(objectSpaceMock.Object, task, applicationMock.Object, true)); Assert.AreEqual(result, testedAction.Enabled.ResultValue); }
Visual Basic
<Test> <TestCase(Priority.High, True)> <TestCase(Priority.Low, False)> Public Sub ActionsInDetailViewTest(ByVal priority As Priority, ByVal result As Boolean) Dim actionsCriteriaViewController As ActionsCriteriaViewController = New ActionsCriteriaViewController() Dim testedController As ViewController = New ViewController() Dim testedAction As SimpleAction = New SimpleAction(testedController, "High Priority", String.Empty) testedAction.TargetObjectsCriteria = "Priority = 2" Dim task As DemoTask = New DemoTask(Session.DefaultSession) task.Priority = priority Dim objectSpaceMock = New Mock(Of IObjectSpace)() objectSpaceMock.Setup(Function(os) os.Contains(It.IsAny(Of Object)())).Returns(True) objectSpaceMock.Setup(Function(os) os.GetEvaluatorContextDescriptor(GetType(DemoTask))).Returns(New EvaluatorContextDescriptorDefault(GetType(DemoTask))) Dim applicationMock = New Mock(Of XafApplication)() Dim frame As Frame = New Frame(applicationMock.Object, TemplateContext.View, actionsCriteriaViewController, testedController) frame.SetView(New DetailView(objectSpaceMock.Object, task, applicationMock.Object, True)) Assert.AreEqual(result, testedAction.Enabled.ResultValue) End Sub

However, the [TestCase(Priority.High, true)] case will fail because the Action is disabled. From the How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View article, we know that an Action is disabled by its target criteria in the ActionsCriteriaViewController.UpdateAction method. Let's put a breakpoint in it. The interesting part is:

C#
protected virtual void UpdateAction(ActionBase action, string criteria) { if(action.Active && (action.Enabled || action.Enabled.Contains(EnabledByCriteriaKey))) { bool enable = true; if(IsActionForUpdate(action) && (action.SelectionContext != null)) { IList selectedObjects = action.SelectionContext.SelectedObjects; if(selectedObjects == null || selectedObjects.Count == 0) { enable = false; } else { // ... } action.Enabled.SetItemValue(EnabledByCriteriaKey, enable); } }

SelectionContext is our DetailView now and its SelectedObjects property returns an empty list of objects. The DetailView.SelectedObjects property implementation is:

C#
public override IList SelectedObjects { get { if(CurrentObject != null) { return new Object[] { CurrentObject }; } else { return new Object[] { }; } } }

The Detail View CurrentObject is null. This property is implemented as follows:

C#
public override object CurrentObject { get { return currentObject; } set { if(currentObject != value) { // ... Guard.CheckObjectFromObjectSpace(ObjectSpace, value); if(OnQueryCanChangeCurrentObject()) { UnsubscribeFromObject(currentObject); currentObject = ObjectSpace.GetObject(value); // ... } } } }

Let's put a breakpoint into the property setter and re-run the test in debug mode. We will see that the ObjectSpace.GetObject method returns nothing since we didn't mock it. Let's do this.

C#
objectSpaceMock.Setup(os => os.GetObject(It.IsAny<object>())).Returns<object>(obj => obj);
Visual Basic
objectSpaceMock.Setup(Function(os) os.GetObject(It.IsAny(Of Object)())).Returns(Of Object)(Function(obj) obj)

Now, everything works and the entire test code is:

C#
[Test] [TestCase(Priority.High, true)] [TestCase(Priority.Low, false)] public void ActionsInDetailViewTest(Priority priority, bool result) { ActionsCriteriaViewController actionsCriteriaViewController = new ActionsCriteriaViewController(); ViewController testedController = new ViewController(); SimpleAction testedAction = new SimpleAction(testedController, "High Priority", string.Empty); testedAction.TargetObjectsCriteria = "Priority = 2"; DemoTask task = new DemoTask(Session.DefaultSession); task.Priority = priority; var objectSpaceMock = new Mock<IObjectSpace>(); objectSpaceMock.Setup(os => os.Contains(It.IsAny<object>())).Returns(true); objectSpaceMock.Setup(os => os.GetObject(It.IsAny<object>())).Returns<object>(obj => obj); objectSpaceMock.Setup(os => os.GetEvaluatorContextDescriptor(typeof(DemoTask))).Returns(new EvaluatorContextDescriptorDefault(typeof(DemoTask))); var applicationMock = new Mock<XafApplication>(); Frame frame = new Frame(applicationMock.Object, TemplateContext.View, actionsCriteriaViewController, testedController); frame.SetView(new DetailView(objectSpaceMock.Object, task, applicationMock.Object, true)); Assert.AreEqual(result, testedAction.Enabled.ResultValue); }
Visual Basic
<Test> <TestCase(Priority.High, True)> <TestCase(Priority.Low, False)> Public Sub ActionsInDetailViewTest(ByVal priority As Priority, ByVal result As Boolean) Dim actionsCriteriaViewController As ActionsCriteriaViewController = New ActionsCriteriaViewController() Dim testedController As ViewController = New ViewController() Dim testedAction As SimpleAction = New SimpleAction(testedController, "High Priority", String.Empty) testedAction.TargetObjectsCriteria = "Priority = 2" Dim task As DemoTask = New DemoTask(Session.DefaultSession) task.Priority = priority Dim objectSpaceMock = New Mock(Of IObjectSpace)() objectSpaceMock.Setup(Function(os) os.Contains(It.IsAny(Of Object)())).Returns(True) objectSpaceMock.Setup(Function(os) os.GetObject(It.IsAny(Of Object)())).Returns(Of Object)(Function(obj) obj) objectSpaceMock.Setup(Function(os) os.GetEvaluatorContextDescriptor(GetType(DemoTask))).Returns(New EvaluatorContextDescriptorDefault(GetType(DemoTask))) Dim applicationMock = New Mock(Of XafApplication)() Dim frame As Frame = New Frame(applicationMock.Object, TemplateContext.View, actionsCriteriaViewController, testedController) frame.SetView(New DetailView(objectSpaceMock.Object, task, applicationMock.Object, True)) Assert.AreEqual(result, testedAction.Enabled.ResultValue) End Sub

See Also:
This series contains the following articles:

  1. How to write unit tests for XAF Actions, Controllers, and other custom UI logic
  2. How to unit test Action's enabled/disabled state based on user permissions
  3. How to unit test whether object property changes via Actions were successfully committed
  4. How to unit test object queries by criteria and Detail View creation
  5. How to unit test event handlers in Controllers
  6. How to unit test New Action's custom business logic based on parent and nested Views
  7. How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View
  8. How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in Detail View (current)
  9. How to unit test localized strings from CaptionHelper (Approach 1)
  10. How to unit test localized strings from CaptionHelper (Approach 2)
  11. How to unit test custom logic in XAF/XPO business classes

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.