Testing GWT without GwtTestCase

223 views
Skip to first unread message

Thad

unread,
May 20, 2013, 9:42:55 AM5/20/13
to google-we...@googlegroups.com
Can anyone clarify for me this Google testing blog entry? http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html

Model, view, presenter I think I'm clear on (ha! yeah, sure), but I'm trying to understand the Server.class. It's described as "a completely standard backend with no dependency on GWT." (Their emphasis.) So what is that? Does that mean not a service interface and not a service Impl class? If so, where is the RPC coming in?

What I'm trying to do--what I think many would like to do--is test RPC methods without the RPC delay. Right now I do that by calling my ServiceImpl methods in my JUnit test. This often forces me to mock an HttpSession object and add an extra method so I can pass that in (since getThreadLocalRequest() is protected). Testing through my client would be preferable but the delay is a pain.

Goktug Gokdogan

unread,
May 20, 2013, 2:14:42 PM5/20/13
to google-web-toolkit
On Mon, May 20, 2013 at 6:42 AM, Thad <thad.hu...@gmail.com> wrote:
Can anyone clarify for me this Google testing blog entry? http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html

Model, view, presenter I think I'm clear on (ha! yeah, sure), but I'm trying to understand the Server.class. It's described as "a completely standard backend with no dependency on GWT." (Their emphasis.) So what is that? Does that mean not a service interface and not a service Impl class? If so, where is the RPC coming in?


That is the Async interface. Technically, it still depends on GWT for the AsyncCallback interface.
I think what they actually meant is, it doesn't depend on any native methods so it is easy to mock.
 
What I'm trying to do--what I think many would like to do--is test RPC methods without the RPC delay. Right now I do that by calling my ServiceImpl methods in my JUnit test. This often forces me to mock an HttpSession object and add an extra method so I can pass that in (since getThreadLocalRequest() is protected). Testing through my client would be preferable but the delay is a pain.


Refactor your service out of your servlet. A common useful pattern is:

class ServerServlet extends RemoteServiceServlet implements ServerService {
  ServerServiceImpl service = ....

  public void someServerMethod() {
    service.someServerMethod();
  }
}

class ServerServiceImpl implements ServerService {
  // implement your logic here
}
Then write the test against for ServerServiceImpl which doesn't depend on any servlet internals. Note that, this is pattern also useful if you need to call ServerService at server side in production.
 

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Thad

unread,
May 21, 2013, 1:28:12 PM5/21/13
to google-we...@googlegroups.com

On Monday, May 20, 2013 2:14:42 PM UTC-4, Goktug Gokdogan wrote:


On Mon, May 20, 2013 at 6:42 AM, Thad <thad.hu...@gmail.com> wrote:
Can anyone clarify for me this Google testing blog entry? http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html

Model, view, presenter I think I'm clear on (ha! yeah, sure), but I'm trying to understand the Server.class. It's described as "a completely standard backend with no dependency on GWT." (Their emphasis.) So what is that? Does that mean not a service interface and not a service Impl class? If so, where is the RPC coming in?


That is the Async interface. Technically, it still depends on GWT for the AsyncCallback interface.
I think what they actually meant is, it doesn't depend on any native methods so it is easy to mock.
 
What I'm trying to do--what I think many would like to do--is test RPC methods without the RPC delay. Right now I do that by calling my ServiceImpl methods in my JUnit test. This often forces me to mock an HttpSession object and add an extra method so I can pass that in (since getThreadLocalRequest() is protected). Testing through my client would be preferable but the delay is a pain.


Refactor your service out of your servlet. A common useful pattern is:

class ServerServlet extends RemoteServiceServlet implements ServerService {
  ServerServiceImpl service = ....

  public void someServerMethod() {
    service.someServerMethod();
  }
}

class ServerServiceImpl implements ServerService {
  // implement your logic here
}
Then write the test against for ServerServiceImpl which doesn't depend on any servlet internals. Note that, this is pattern also useful if you need to call ServerService at server side in production.

Is that safe? My services makes heavy use of the HttpSession. At a minimum, I store the user's connection to the legacy server app I work with, but there are other things, too--tables last queried, images retrieved, etc. This is why I wish I could override getThreadLocalRequest() with a mock for testing.

To have an entirely separate class, I'd have to instantiate it with each RPC call so the session object wouldn't get stomped on by another user. I'm worried about that overhead once I'm out of development and test and into production. Failing that I could pass the session in with the call, but then I don't see the point of a separate class. I could just have something like this for each public method.

@Override
public LoginInfo doLogin(String server, String name, String passwd) {
  return doLogin(getThreadLocalRequest().getSession(true), server, name, password);
}

private LoginInfo doLogin(HttpSession session, String server, String name, String passwd) {
  MyApp app = new MyApp();
  // prep more params and log in
  ...
  app.login(server, name, passwd, param0...);
  // remember session
  ...
  return app.getLoginInfo();
}

Jens

unread,
May 21, 2013, 3:21:34 PM5/21/13
to google-we...@googlegroups.com
I am also in the process of making GWT-RPC method implementation independent of GWT-RPC/Servlet for easier testing. I don't really bother about introducing new short lived objects created for each request. Short living objects are not a real problem in todays JVMs and you can probably save a lot more resources by optimizing heavy weight algorithms, etc. But as always: Only start optimizing if you have to because some service is too slow or consumes too much resources. As long as everything works fine just write clear, easy to understand code.

So in case of GWT-RPC + command pattern you maybe end up with something like:

public Result execute(Command cmd) {
  HttpSession session = getThreadLocalRequest().getSession();
  //HttpSession needs to be mocked or stubbed
  Cache cache = new SessionBackedCache(session);
  //following code does not know anything about servlets and GWT-RPC
  CommandDispatcher dispatcher = new DefaultCommandDispatcher();
  CommandExecutor executor = new DefaultCommandExecutor(cache, dispatcher);
  Result result = executor.execute(cmd);
  return result;
}

With this code you can unit test SessionBackedCache, DefaultCommandDispatcher, DefaultCommandExecutor and then I would think twice if I would write a test case for the GWT-RPC method itself as its implementation is super simple. When using an injection library like google-guice this code would probably be even shorter.

If I could avoid it, I would never delegate to a private method, like in your example code, and then make this private method accessible again using reflection during tests. IMHO tests should cover public methods and not private ones.

-- J.

Joseph Lust

unread,
May 21, 2013, 5:11:00 PM5/21/13
to google-we...@googlegroups.com
Early on in the presentation Erik also mentions a recently released GWT Mockito setup that might benefit your non-GwtTestCase goals.



Sincerely,
Joseph
Reply all
Reply to author
Forward
0 new messages