Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Testing of smartgwt server-side datasources

    Hello,

    I'm using Smartgwt EE/Pro eval 3.0 and I'm trying to check if it is possible to write good integration or mock tests of server side smartgwt datasources.
    I've read "StandaloneDataSourceUsage" documentation but I really don't know how to configure paths in server.properties file.

    When I try to load datasource from my test code:
    Code:
            DataSource ds = DataSourceManager.get("id_of_DS");
            List records = ds.fetch(new Criteria());
            Assert.assertNotNull(records);
    I'm getting and error:
    Code:
    Problem loading builtinTypes.xml
    Exception when loading from /isomorphic/system/schema/builtinTypes.xml:
    java.io.FileNotFoundException: /isomorphic/system/schema/builtinTypes.xml (No such file or directory)
    Where can I find good example of integration (or unit) test of DS?

    #2
    This is covered right in the Standalone DataSource docs:

    NOTES

    Because we are not running inside a servlet container, Smart GWT's built-in logic to work out where its application root is does not work. Therefore, you need to manually set a "webRoot" in your server.properties file. The webRoot should point to the root folder of your application (note for SmartGWT applications, this is typically the "war" subfolder of your project). Example entries:

    webRoot: /home/testUser/myProject

    or:

    webRoot: C:\Projects\MyProject\war

    Comment


      #3
      Thanks for your reply!

      I tried it before: it does not work.
      Maybe I should tell more about my project structure:
      My project is "mavenized". I have lots of modules (libraries), some of them will provide datasources.
      So I try to write and run datasource test outside main appliaction: now in one of modules. I don't have there either any "webroot" dir nor unpacked smartgwt ee directories.

      As I understand smartgwt engine should load neccesary internal "xml" fiels from classpath (I provide smargwtee.jar in claspath). I think I have to point (somehow) location of these files in classpath in "com/smartclientee/public" package, but I don't know how to write proper path epression.

      Now ISCFile is looking for file in filesystem (I see exception at java.io.FileInputStream) but it should look for file in classpath.
      How to fix it?

      Comment


        #4
        Use __USE_CONTAINER__ as the value for webRoot if you will be using a .war but not actually deploying files to disk. This is explained right in server.properties itself.

        We don't support loading DataSource definitions (.ds.xml files) from the classpath (and we don't generally think this is a good idea). However, if you want to support this, you could use DataSource.addDynamicDSGenerator() to do it - see docs for this method.

        Comment


          #5
          I don't agree with you: loading ds from classpath is very useful. Especially when you have lots of independent modules.

          I tried to solve this problem ("lack of functionality"). I configured my maven project to unpack contents of spartgwtee.jar to separate temporary dorectory.

          server.properties (fragment):
          Code:
          webRoot: ./
          isomorphicPathRootRelative: target/test-smartgwt/com/smartclientee/public/sc

          Now smartgwt egnine loads internal ds definitions.
          Bot my "plugins" which load ds definitions from classpath cannot work without ServletContext.

          I'm getting such errors:
          Code:
          java.lang.Exception: RequestContext is missing the ServletContext.  Please ensure you privide either a PageContext, a Servlet, or a ServletContext to your RequestContex.instance() call.
          	at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:225)
          	at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:70)
          	at com.isomorphic.hibernate.HibernateDataSource.initStaticConfigAndSessionFactory(HibernateDataSource.java:468)
          	at com.isomorphic.hibernate.HibernateDataSource.getConfigFromMappedClass(HibernateDataSource.java:4812)
          	at com.isomorphic.hibernate.HibernateDataSource.fromMappedClass(HibernateDataSource.java:4790)
          	at com.isomorphic.hibernate.HibernateDataSource.init(HibernateDataSource.java:171)
          	at com.isomorphic.datasource.DataSource.initialize(DataSource.java:374)
          	at com.isomorphic.datasource.BasicDataSource.fromConfig(BasicDataSource.java:158)
          	at com.isomorphic.datasource.DataSource.fromConfig(DataSource.java:359)
          	at com.isomorphic.datasource.DataSource.fromXML(DataSource.java:534)
          when I try to upload definition in such line of code:
          Code:
           DataSource ds = DataSource.fromXML(read, dsReq);
          "dsReq" is of DSRequest type.

          I don't know what to put into this object to work properly?
          ServletContext? But I don't have servlet context in standalone appliaction (such as "junit test").

          Comment


            #6
            I tried simpler example: to load ds definition from directory usung code
            Code:
                    DSRequest dsReq = new DSRequest("ds_baseScreenDef", "fetch");
                    dsReq.execute().getDataList();
            And I get error:

            Code:
            java.lang.Exception: RequestContext is missing the ServletContext.  Please ensure you privide either a PageContext, a Servlet, or a ServletContext to your RequestContex.instance() call.
            	at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:225)
            	at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:70)
            	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:206)
            	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
            	at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:1945)
            [...]

            Comment


              #7
              Taking a step back - if this exploration is motivate by testing (as the thread subject says) you should abandon it. Test in a real servlet environment or you will not be able to test all features of your application.

              As far the errors you'er getting, they are coming from the fact that you use lookupStyle="spring" in your DMI and we currently locate the Spring BeanFactory via the servletContext.

              Comment


                #8
                How does the SmartGWT code find the servletContext? Is there a way to make an instance of org.springframework.mock.web.MockServletContext accessible to the DataSourceManager, for example?

                I'm trying to unit test the datasources as well. I would like to unit test each "tier" of the application as narrowly as possible, in order to pinpoint issues as they arise--preferably before they're committed into the rest of the development stream.

                -joe

                Comment


                  #9
                  Perhaps a lookupStyle of "factory", using a factory class to grab the sessionFactory from the Spring context and hand it to SmartGWT would work. This is probably more straightforward than trying to mock up a valid request + context.
                  I'll post an update later.

                  -joe

                  Comment


                    #10
                    We really recommend against that strategy - you're going to end up with a bunch of code that tests intermediate results in the middle of subsystems that may be refactored in the future, destroying the value of the tests.

                    Instead, we recommend designing tests that verify user-visible results but which depend on the correct operation of intermediate subsystems. You don't have infinite time to write tests and such tests are both more valuable now and more likely to last.

                    As far as the ServletContext, it is provided by the InitServlet (or ContextListener in 3.1d). As far as mocking, even if you could provide a MockServletContext this would still not necessarily allow you to run standalone DataSource tests since DMI logic and subsystems such as Declarative Security depend on access to an authenticated user and other aspects of the servlet environment - and this is a correct dependency.

                    While you could, in theory, mock all of this, see above for why that's not an effective approach.

                    Comment


                      #11
                      Thanks for reply.

                      I also try to write tests as near as possible to real code.
                      My experience is that writing unit tests (or integratiuon tests in modules) is a far more productive than writing tests "N tiers above" in aplication which uses module.

                      Look: I have one module (jar) with datasource and N applications which use this module - should I write one test or N tests (maybe copy-paste)?

                      My idea is also to mock servlet context - so I'm interestend in Joe's results.

                      Comment


                        #12
                        It's foolish to copy and paste test code and that's not what we'd recommend. Obviously you can create a test that focuses on one .jar or one feature without copying and pasting.

                        The actual point we have made is that it's a great deal of effort to mock the entire servlet environment, and the resulting tests are less valuable.

                        Comment


                          #13
                          Mocking the ServletContext looks like a dead end.

                          The factory method sort of works. I give it a "sort of", because:
                          a) This requires modification of the server.properties. I haven't found a way to programmatically configure this, although I didn't look very hard.

                          b) The tests that can be accomplished are rudimentary:
                          Loop through the files in the "war/ds" directory to build a list of datasources.
                          For each datasource name (derived from the file name) try/catch loading the datasource and fetching a single record.
                          In the exception handler, store the failing datasource name and error message.
                          At the end of the test spit out the failure information, if any.
                          Assert that the failure list is empty.

                          c) Manual verification is required in order to pull any erroroneous configuration info out of the console output.

                          Comment


                            #14
                            Any conclusion in that? How to test the DataSource(ds.xml) results using Junit or Standalone code?

                            Comment


                              #15
                              See the "Standalone DataSource Usage" overview in the docs.

                              Comment

                              Working...
                              X