Doubts about GWTTestCase scenarios, GWTTestCase vs TestCase ... mocking?

21 views
Skip to first unread message

Rebornspirit

unread,
May 11, 2007, 6:50:25 AM5/11/07
to Google Web Toolkit
Hi,

I'm trying to implement the GWTTestCase approach for a couple of
scenarios and have serious doubts that I'm doing thing the 'right'
way, so help me out here ;-)

1. To get the test classes which extend GWTTestCase compiled I needed
to add <inherits name="com.google.gwt.junit.JUnit"/> to the .gwt.xml
file, is this the correct way because I couldn't find that on the
site. Secondly I'm adding this to my root .gwt.xml file of my GWT
application, is this correct or should I make a new .gwt.xml file to
serves as the root of my test package and which will inherit my
application root module?

2 Scenario 1: Testing a client side view model (pojo) + property
change support

public void testSearchCriteriaPropertyChange() {
delayTestFinish(10000);
final String SEARCH_CRITERIA = "testString";
final SearchModel model = new SearchModel();

model.addPropertyChangeListener("searchCriteria", new
PropertyChangeListener() {

public void propertyChange(PropertyChangeEvent event) {
String searchCriteria = (String) event.getNewValue();
assertEquals(SEARCH_CRITERIA, searchCriteria);
finishTest();
}
});

model.setSearchCriteria(SEARCH_CRITERIA);
}

With the example above I have the following doubts:
- Why must I extend from the GWTTestCase when testing a simple pojo,
do I really need the extra overhead of booting up the shell? Can't I
just extend from JUnit TestCase instead? Perhaps some explanation on
when to use the GWTTestCase would be great (scenarios)!

2. Scenario 2: Testing GWT RPC

public void findMatches() {
delayTestFinish(10000);

SearchGWTService.App.getInstance().getMatches("dook", new
AsyncCallback() {
public void onFailure(Throwable cause) {
fail(cause.getMessage());
}

public void onSuccess(Object result) {
List matches = (ArrayList) result;
finishTest();
}
});
}

Doubts:
- My SearchGWTService implementation on the server-side is a Spring
bean, and it is also depending on multiple other beans. It is possible
to test a GWT RPC call in isolation or doesn't that make sense?
Mocking?
- Because my service implementation is a Spring bean, the Spring
container has to be booted on startup. I use for this a tomcat
instance which get started and during development I link my shell to
the tomcat instance. So now I'm in trouble because when I'm starting
the test case, the shell gets booted but he is using the internal
tomcat I guess which causes my test to fail because he can't find the
mapped service url on the server-side ... well duhh because it only
exists in my tomcat (with loaded spring ctx) application :-)

So ... at the end ... I'm really in doubt on what to test with GWT, is
there a lot I can unit test or is it mostly integration testing, like
the rpc stuff?

Help ... ;-)

Grtz

M.

Maarten Volders

unread,
May 14, 2007, 3:59:24 AM5/14/07
to Google Web Toolkit
Anyone ... who would like to talk about which test scenarios he is using on GWT code?
Because initially I thought I could test (integration test / unit test) the complete front end but that seems to be a dream... I guess I'm going with Selenium for front end testing.

Steiner Dominik, (QX59311)

unread,
May 16, 2007, 4:58:26 AM5/16/07
to Google-We...@googlegroups.com

Hi Maarten,

 

this post might be interesting for you:

 

http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/ecb25ba44760c88c/b3a188dfa6de2418?lnk=gst&q=gwttestcase&rnum=1#b3a188dfa6de2418

 

I’m no expert with the GWTTestCase and unfortunatly I’m not using it too much as I would like (especially because it takes quite a while to run each test), but I’ll try to answer your questions.

 

  1. I would create a separate gwt.xml for your test cases. <inherits name="com.google.gwt.junit.JUnit"/>  it necessary.

Especially I found that you really don’t need a gwt.xml file for your test cases which declares and EntryPoint, as you just might want to test a method of a UI class.

And it makes a lot of sense to have multiple gwt.xml files for different TestCases, so that you can specify a source path which doesn’t have to be all of /client, but if you just

Are testing the package client.ui.table it might make sense to only add that to the source path of your module. (so that the compilation is done more rapidly)

 

  1. If you are not using any GWT code in your client classes, you might as well just use TestCase.

Scenario 2: If you’re using Spring you might want to have a look at AbstractDependencyInjectionSpringContextTests.

This makes integration tests really simple and you don’t have to use GWTTestCase either. As you might read in the post above

The GWTTestCase is started with an internal Tomcat so that you can’t use an external server.

 

As mentioned above, currently I’m only using GWTTestCase for client UI classes which are using GWT code.

But even then not too much because of the long startup time it infers to compile the GWT code and execute the tests.

 

Perhaps others might chime in here and give there two cents too.

 

Dominik

 

 


<br

Dan Morrill

unread,
May 16, 2007, 11:58:20 AM5/16/07
to Google-We...@googlegroups.com

Hello!

The unit testing functionality is definitely confusing at first.  I think you're pretty much on the right track, though I have a few comments below.

On 5/11/07, Rebornspirit < maarten...@gmail.com> wrote:
1. To get the test classes which extend GWTTestCase compiled I needed
to add <inherits name=" com.google.gwt.junit.JUnit"/> to the .gwt.xml
file, is this the correct way because I couldn't find that on the
site.

The JUnit functionality relies heavily on GWT module inheritance.  Because of this, it's important to be comfortable with the general notion of a GWT module first.  If you're not yet comfortable, this information may be helpful to you:  http://code.google.com/support/bin/answer.py?answer=55197&topic=10211

As far as JUnit is concerned, the most important thing to understand about modules is how they inherit.  Inheriting a module in GWT is much like including a header file in C:  all the definitions set in the parent module are copied directly into the "namespace" of the child module inheriting the parent.

The intended model for developing JUnit tests for a GWT application is that you build your actual application module as you normally would.  Then, you create a second module intended only for testing;  that module inherits your normal application's module and adds the JUnit-related stuff.  You can think of this as a bit like "subclassing" your application module, to add some additional material just for testing.

For instance, suppose you have this module XML file, which defines the module com.company.app.MyApp:
<module>
  <inherits name="com.google.gwt.user.User"/>
  <servlet path="/rpc" class="com.company.app.server.MyRPCServlet"/>
  <entry-point class="com.company.app.client.MyEntryPoint"/>
  <source path="client"/> <!-- this is the default and so is optional -->
  <public path="public"/> <!-- this is the default and so is optional -->
</module>

To write JUnit tests, we generally intend that you create a child module like this, perhaps named com.company.app.MyAppTest:
<module>
  <inherits name="com.company.app.MyApp"/>
  <inherits name="com.google.gwt.junit.JUnit"/>
  <source path="test"/>
</module>

This "child" MyAppTest module has two simple effects:  it loads in the JUnit-related infrastructure;  it adds the package "com.company.app.test" to the list of Java packages containing translatable code.  Otherwise it is identical to the MyApp "parent" module. This allows you to refer to com.company.app.MyApp when you deploy, and com.company.app.MyAppTest during testing, which in turn keeps your test-related code separate from your deployment code.

Given the above modules, you'll have 3 relevant Java packages:
com.company.app.client.* -- GWT client-side application classes
com.company.app.server.* -- servlets, including the com.company.app.server.MyRPCServlet RPC service implementation
com.company.app.test.* -- all your JUnit-related test code;  ignored during deployment and debugging; used during testing

As a final note, in this configuration your actual GWTTestCase class needs to return the module name "com.company.app.MyAppTest" in its getModuleName() method.  (This is because only MyTestApp includes the .test.* subpackage in the translatable-code list -- the MyApp module does not.  Without that, the GWT environment won't be able to locate your test case class.)


- Why must I extend from the GWTTestCase when testing a simple pojo,
do I really need the extra overhead of booting up the shell? Can't I
just extend from JUnit TestCase instead? Perhaps some explanation on
when to use the GWTTestCase would be great (scenarios)!

You are 100% correct -- you do NOT need to extend GWTTestCase just to test things like POJOs, server-side utility classes, etc.  You only need to extend GWTTestCase to test classes that need to use either GWT RPC, or Deferred Binding in some way.

Put another way, if you are using 'ant' to automate your build, you would generally have your "test" target run two commands:  one for the standard JUnit TestRunner to test your POJOs/utility classes/etc., and a second one for the GWTTestRunner subclass to handle any of your GWT-related code.
 

- My SearchGWTService implementation on the server-side is a Spring
bean, and it is also depending on multiple other beans. It is possible
to test a GWT RPC call in isolation or doesn't that make sense?
Mocking?

I am not quite sure what you are asking here, so my answer may not be useful; feel free to call me out if it's not helpful. :)

That said -- I would agree that a best practice would be to segment your RPC service implementation (in this case, your SearchGWTService) so that it does as much work as possible in externalized, easily-testable classes.  For example, you might be using a POJO as the object you're passing back and forth between client and server.  If you move all actual processing of that POJO into an external utility class, then you can test that class in pure Java with the standard JUnit TestRunner.  (I believe this is what you were referring to when you mentioned "mocking".)  Your GWTTestCase would then be fairly narrowly constrained to testing whether your servlet is properly serializing, deserializing, and routing the POJOs appropriately during method calls.
 

- Because my service implementation is a Spring bean, the Spring
container has to be booted on startup. I use for this a tomcat
instance which get started and during development I link my shell to
the tomcat instance.

Yes, this is probably a point of true difficulty.  This is similar to the case where you want to do away with the Servlet entirely, and build Spring beans that can handle RPC requests without having to have a Servlet at all. Unfortunately, that is pretty difficult in 1.3.3, though Rob Jellinghaus has contributed a great patch that refactors the RPC server infrastructure and will make this possible in 1.4.

In other words, this could be tricky to do, today, but may get better in 1.4.  It is actually possible to get Spring set up in the hosted mode Tomcat, although it's something of a pain.  I'd try the technique I described above, about trying to refactor into utility classes and constrain your Servlet, and see if that gets you where you need to be.
 

So ... at the end ... I'm really in doubt on what to test with GWT, is
there a lot I can unit test or is it mostly integration testing, like
the rpc stuff?

Hopefully I have answered much of this, or at least given you some food for thought.  Thanks for reading this far!  As I said way up at the top, I think your instincts are correct and you are on the right track.  Hopefully I've filled in some of the details for you.

- Dan Morrill
Reply all
Reply to author
Forward
0 new messages