Ticket T915268
Visible to All Users

How to test a controller with the TargetViewId property specified and get a localized string from CaptionHelper

created 5 years ago (modified 5 years ago)

[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.

Show previous comments (1)
DevExpress Support Team 5 years ago

    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.

    KY KY
    Kalem Yazılım 5 years ago

      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,

      C#
      [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

      KY KY
      Kalem Yazılım 5 years ago

        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.

        Answers approved by DevExpress Support

        created 5 years ago

        Thank you for this clarification, Kalem. Now I see that the problem is the created List View does not have an Id. You can create a ListView descendant and set the required Id value in its constructor.

        C#
        public class MyListView : ListView { public MyListView(CollectionSourceBase collectionSource, ListEditor listEditor, bool isRoot) : base(collectionSource, listEditor, isRoot) { Id = "PurchaseInvoice_ListView"; } }
          Comments (2)
          KY KY
          Kalem Yazılım 5 years ago

            Hello Gosha,

            I couldn't determine a solution like that. I think there is no way to found the exact solution without know deep knowledge the class structure. If you accept, I would like to share my new test cases which i failed with you in future.

            I tested your solution and solved my problem.

            Thank you.

            Have a nice day.

            DevExpress Support Team 5 years ago

              You are welcome, Kalem! Sure! We would like to collect more customer test scenarios to better understand what issues developers face when writing a unit test for an XAF application. Feel free to share your test cases.

              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.