Test Scenario
Our task is the same as the one described in the How to unit test localized strings from CaptionHelper (Approach 1) article. We, however, will use another approach to test if our localized string is correctly applied.
Unit Test Implementation
Imagine we added a localization item and we want to test if CaptionHelper returns a correct localized string.
XML<Application Title="MySolution">
<Localization>
<LocalizationGroup Name="Messages">
<LocalizationItem Name="Test" Value="Test" IsNewNode="True" />
</LocalizationGroup>
</Localization>
</Application>
Our test will be:
C#using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Core;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Utils;
using Moq;
using NUnit.Framework;
using MySolution.Module;
namespace MySolution.Tests {
[TestFixture]
public class CaptionHelperTests {
[Test]
public void Test2() {
Assert.AreEqual("Test", CaptionHelper.GetLocalizedText("Messages", "Test"));
}
}
}
Visual BasicImports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.Core
Imports DevExpress.ExpressApp.DC
Imports DevExpress.ExpressApp.Utils
Imports Moq
Imports NUnit.Framework
Imports MySolution.[Module]
<TestFixture>
Public Class CaptionHelperTests
<Test>
Public Sub Test2()
Assert.AreEqual("Test", CaptionHelper.GetLocalizedText("Messages", "Test"))
End Sub
End Class
From How to unit test localized strings from CaptionHelper (Approach 1) we know that we need to call the CaptionHelper.Setup method to make our test work. XafApplication calls this method from the SetupModelApplication private method. And SetupModelApplication is called from the XafApplication Setup public method. Thus, to make our test work, we just need to call the Setup method in it. We won't create a real XafApplication - it's a time and memory consuming operation. We will mock it.
C#var applicationMock = new Mock<XafApplication>();
applicationMock.CallBase = true;
Visual BasicDim applicationMock = New Mock(Of XafApplication)()
applicationMock.CallBase = True
We need to set the Mock<T>.CallBase property to true to be able to use real method implementations of the XafApplication class. The Setup method has the following signature:
C#public void Setup(ExpressApplicationSetupParameters parameters);
Thus, we need to create an ExpressApplicationSetupParameters object. Its constructor is:
C#public ExpressApplicationSetupParameters(string applicationName, IObjectSpaceProvider objectSpaceProvider, ControllersManager controllersManager, ModuleList modules);
We are not interested in the application name and will pass null/Nothing to this parameter. Then, we need an IObjectSpaceProvider instance - we will mock it. We will create a ControllersManager instance and create a ModuleList with our Module.
C#ModuleList moduleList = new ModuleList {
new MySolutionModule()
};
var objectSpaceProviderMock = new Mock<IObjectSpaceProvider>();
ExpressApplicationSetupParameters setupParameters = new ExpressApplicationSetupParameters(null, objectSpaceProviderMock.Object, new ControllersManager(), moduleList);
applicationMock.Object.Setup(setupParameters);
Visual BasicDim moduleList As ModuleList = New ModuleList From {
New MySolutionModule()
}
Dim objectSpaceProviderMock = New Mock(Of IObjectSpaceProvider)()
Dim setupParameters As ExpressApplicationSetupParameters = New ExpressApplicationSetupParameters(Nothing, objectSpaceProviderMock.Object, New ControllersManager(), moduleList)
applicationMock.Object.Setup(setupParameters)
Now, run our test. It fails with the following message and call stack:
CodeValue cannot be null.
Parameter name: entityStore
Call StackDevExpress.Data.v19.2.dll!DevExpress.Utils.Guard.ThrowArgumentNullException(string propName) Line 108 C# DevExpress.Data.v19.2.dll!DevExpress.Utils.Guard.ArgumentNotNull(object value, string name) Line 51 C# DevExpress.ExpressApp.v19.2.dll!DevExpress.ExpressApp.Utils.Guard.ArgumentNotNull(object argumentValue, string argumentName) Line 58 C# DevExpress.ExpressApp.v19.2.dll!DevExpress.ExpressApp.DC.TypesInfo.AddEntityStore(DevExpress.ExpressApp.DC.IEntityStore entityStore) Line 228 C# DevExpress.ExpressApp.v19.2.dll!DevExpress.ExpressApp.XafApplication.AddEntityStoresIntoTypesInfo() Line 424 C# DevExpress.ExpressApp.v19.2.dll!DevExpress.ExpressApp.XafApplication.Setup(DevExpress.ExpressApp.ExpressApplicationSetupParameters parameters) Line 1589 C#
This happens because there is a check in the AddEntityStore method that the passed entityStore
parameter is not null.
C#public void AddEntityStore(IEntityStore entityStore) {
Guard.ArgumentNotNull(entityStore, "entityStore");
// ...
}
It's null in our case. The XafApplication method that calls the AddEntityStore method is AddEntityStoresIntoTypesInfo. Its implementation is:
C#private void AddEntityStoresIntoTypesInfo() {
TypesInfo localTypesInfo = typesInfo as TypesInfo;
if(localTypesInfo != null) {
foreach(IObjectSpaceProvider objectSpaceProvider in objectSpaceProviders) {
localTypesInfo.AddEntityStore(objectSpaceProvider.EntityStore);
}
}
}
Thus, the IObjectSpaceProvider instance we mocked does not have its EntityStore specified. Let's mock this property.
C#var entityStoreMock = new Mock<IEntityStore>();
objectSpaceProviderMock.Setup(o => o.EntityStore).Returns(entityStoreMock.Object);
Visual BasicDim entityStoreMock = New Mock(Of IEntityStore)()
objectSpaceProviderMock.Setup(Function(o) o.EntityStore).Returns(entityStoreMock.Object)
Now, our test passes. Its entire code:
C#[Test]
public void Test2() {
var applicationMock = new Mock<XafApplication>();
applicationMock.CallBase = true;
ModuleList moduleList = new ModuleList {
new MySolutionModule()
};
var entityStoreMock = new Mock<IEntityStore>();
var objectSpaceProviderMock = new Mock<IObjectSpaceProvider>();
objectSpaceProviderMock.Setup(o => o.EntityStore).Returns(entityStoreMock.Object);
ExpressApplicationSetupParameters setupParameters = new ExpressApplicationSetupParameters(null, objectSpaceProviderMock.Object, new ControllersManager(), moduleList);
applicationMock.Object.Setup(setupParameters);
Assert.AreEqual("Test", CaptionHelper.GetLocalizedText("Messages", "Test"));
}
Visual Basic<Test>
Public Sub Test2()
Dim applicationMock = New Mock(Of XafApplication)()
applicationMock.CallBase = True
Dim moduleList As ModuleList = New ModuleList From {
New MySolutionModule()
}
Dim entityStoreMock = New Mock(Of IEntityStore)()
Dim objectSpaceProviderMock = New Mock(Of IObjectSpaceProvider)()
objectSpaceProviderMock.Setup(Function(o) o.EntityStore).Returns(entityStoreMock.Object)
Dim setupParameters As ExpressApplicationSetupParameters = New ExpressApplicationSetupParameters(Nothing, objectSpaceProviderMock.Object, New ControllersManager(), moduleList)
applicationMock.Object.Setup(setupParameters)
Assert.AreEqual("Test", CaptionHelper.GetLocalizedText("Messages", "Test"))
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
- 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) (current)
- How to unit test custom logic in XAF/XPO business classes