[DevExpress Support Team: CLONED FROM T853714: How to unit test Action's enabled/disabled state based on target criteria and selection dependency types in List View]
Hello XAF Team,
First of all, thank you for your detailed information about how to use NUnit framework and Moq library in xaf application testing.
In my real case scenario, there are some differences on this example. Both of my controller and action in this controller have TargetViewId requirement. ( Lets say PurchaseInvoice_ListView )
Let me detail which state i am in,
I merged current topic and this topic solutions ( for accessing model ) but couldn't success.
Firstly I thought I should use Frame's
C#public bool SetView(View view);
method like in example. And
C#public ListView(IModelListView modelListView, CollectionSourceBase collectionSource, XafApplication application, bool isRoot);
this constructor for creating ListView, because Frame should be informed which listview's on it. Now I need IModelListView and from my knowledge I can access this object via application model and used this,
C#IModelListView purchaseInvoiceListView = (IModelListView)applicationMock.Object.Model.Views.First(a => a.Id == "PurchaseInvoice_ListView");
As you know, mocked application's Model property comes null. I used code in 9. NUnit sample for initializing model like this,
C#ModelApplicationCreatorProperties properties = ModelApplicationCreatorProperties.CreateDefault(); ModelApplicationCreator modelApplicationCreator = ModelApplicationCreator.GetModelApplicationCreator(properties); ModelApplicationBase modelApplicationBase = modelApplicationCreator.CreateModelApplication(); IModelApplication modelApplication = (IModelApplication)modelApplicationBase; applicationMock.Setup(a => a.Model).Returns(modelApplication);
I changed the first line in this code according to your sample, I thought some code changes occures on your side because ModelApplicationCreatorPropertiesHelper not exists in 20.1.4 version of your source code which I am using. And mocked Model property successfully.
After that, test failing again because Views property comes null and I couldn't find how xaf populates this property. There are 17 references in CommonInterfaces.cs IModelApplication class Views property. But no ones routed me to solution.
Could you please help me? Either with additional code to my works or solution from scratch while controller and action has TargetViewId.
Have a nice day.
I should declare an information, I don't need to access the localized string from CaptionHelper,
When I implement solution from Unit Tests' 6. topic, and Controller & Action has TargetViewId setting, action always come enabled although not fit the criteria.
I looked the action's active property and saw "active = false ( controller active = false )", "enabled = true ( problem )"
Maybe i can mock the which listview is active now, and controller becomes active, and action can check the criteria.
Because when I remove TargetViewId setting, controller becomes active and action also active. Successfully action "enabled = false ( By Criteria = false )"
Thanks.
Hi Kalem,
I am happy to hear that you are interested in writing unit tests for your XAF application and found my articles useful. We are going to write more articles on this and we need more scenarios from our customers. To assist you with this issue in most efficient way, would you please send us the controller you need to test and clarify what assertion you need to make? In certain scenarios, it's not required to mock every method used in your code. I will be happy to research your business logic in a controller and suggest how to test it.
Hi Gosha,
Extracting the controller and action part will be hard for me, but when I try to simulate the project, I can inform about the main parts.
I have controller ( PurchaseProcessController ) has TargetViewId = "PurchaseInvoice_ListView;PurchaseInvoice_DetailView"
I have action in PurchaseProcessController ( named PostingPurchaseInvoice ) , this action also has TargetViewId = "PurchaseInvoice_ListView;PurchaseInvoice_DetailView"
And I am using this Unit Test method,
[Test] [TestCase(true, true)] [TestCase(true, false)] [TestCase(false, true)] [TestCase(false, false)] public void CheckPostingActionState(bool setNullToTargetViewId, bool workForPostedRecord) { PurchaseProcessController purchaseProcessController = new PurchaseProcessController(); SimpleAction postingPurchaseInvoiceAction = (SimpleAction)purchaseProcessController.Actions.FirstOrDefault(a => a.Id == "PostingPurchaseInvoice"); // with this setting, unit test checking action criteria if (setNullToTargetViewId) { purchaseProcessController.TargetViewId = null; postingPurchaseInvoiceAction.TargetViewId = null; } ActionsCriteriaViewController actionsCriteriaViewController = new ActionsCriteriaViewController(); var applicationMock = new Mock<XafApplication>(); //applicationMock.Object.ConnectionString = Module.Utilities.SessionHelper.ConnectionString; //applicationMock.Setup(a => a.ControllersManager()) //ModelApplicationCreatorProperties properties = ModelApplicationCreatorProperties.CreateDefault(); //ModelApplicationCreator modelApplicationCreator = ModelApplicationCreator.GetModelApplicationCreator(properties); //ModelApplicationBase modelApplicationBase = modelApplicationCreator.CreateModelApplication(); //IModelApplication modelApplication = (IModelApplication)modelApplicationBase; //applicationMock.Setup(a => a.Model).Returns(modelApplication); Frame frame = new Frame(applicationMock.Object, TemplateContext.View, actionsCriteriaViewController, purchaseProcessController); PurchaseInvoice testedPurchaseInvoice = sessionForTest.FindObject<PurchaseInvoice>(CriteriaOperator.Parse("BaseCompany.Oid == CurrentCompanyId() && IsPosted == ?", workForPostedRecord)); List<PurchaseInvoice> purchaseInvoices = new List<PurchaseInvoice> { testedPurchaseInvoice }; var listEditorMock = new Mock<ListEditor>(); listEditorMock.Setup(e => e.GetSelectedObjects()).Returns(purchaseInvoices); listEditorMock.Setup(e => e.SupportsDataAccessMode(It.IsAny<CollectionSourceDataAccessMode>())).Returns(true); listEditorMock.Setup(e => e.SelectionType).Returns(SelectionType.Full); var objectSpaceMock = new Mock<IObjectSpace>(); objectSpaceMock.Setup(os => os.GetEvaluatorContextDescriptor(typeof(PurchaseInvoice))).Returns(new EvaluatorContextDescriptorDefault(typeof(PurchaseInvoice))); //ControllersManager controllersManager = new ControllersManager(); //ApplicationModulesManager applicationModulesManager = new ApplicationModulesManager(controllersManager, ""); //applicationMock.Object.Setup(); //applicationMock.Object.Setup("", new List<IObjectSpaceProvider>(), applicationModulesManager, null); //ModelViewsNodesGenerator.GenerateNodesCore(applicationMock.Object.Model); /* IModelViews iModelViewsNode = applicationMock.Object.Model.AddNode<IModelViews>("Views"); IModelListView purchaseInvoiceListView = iModelViewsNode.AddNode<IModelListView>("PurchaseInvoice_ListView"); purchaseInvoiceListView.ModelClass = applicationMock.Object.Model.AddNode<IModelClass>("PurchaseInvoice"); ((IModelSources)applicationMock.Object.Model).BOModelTypes = new List<Type>() { typeof(PurchaseInvoice) }; ModelBOModelClassNodesGenerator modelBOModelClassNodesGenerator = new ModelBOModelClassNodesGenerator(); modelBOModelClassNodesGenerator.GenerateNodes((ModelNode)applicationMock.Object.Model.BOModel); */ //IModelListView purchaseInvoiceListView = (IModelListView)applicationMock.Object.Model.Views.FirstOrDefault(a => a.Id == "PurchaseInvoice_ListView"); //frame.SetView(new ListView(purchaseInvoiceListView, new CollectionSource(objectSpaceMock.Object, typeof(PurchaseInvoice)), applicationMock.Object, true)); frame.SetView(new ListView(new CollectionSource(objectSpaceMock.Object, typeof(PurchaseInvoice)), listEditorMock.Object)); // Controller and action always be active. Action should be enable while record is not Posted, // and should be disable when record is Posted Assert.AreEqual(!workForPostedRecord, postingPurchaseInvoiceAction.Enabled.ResultValue); Assert.AreEqual(true, postingPurchaseInvoiceAction.Active.ResultValue); }
I use OneTimeSetup for accessing test database and not using inmemorydata.
Shall we continue on this?
Thanks
Hello Gosha,
I prepared an example for further discussing and helping other NUnit test tried customers. Unit test has some commented code, please discard them.
In attachment you can easily see, controller comes deactive and test fails. Also either for posted record or non posted record, action is enabled, this is a problem.
Thanks.