New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use gwteventbinder with guice during unit test #17

Open
fedy2 opened this Issue Mar 10, 2014 · 7 comments

Comments

Projects
None yet
5 participants
@fedy2

fedy2 commented Mar 10, 2014

This is not an issue but a question.
I've a GWT application that uses GIN and gwteventbinder.
I'm writing some unit tests in order to test the client logic so I'm mocking views and services.
In order to run tests faster I'm avoiding GWTTestCase implementation and trying to run the tests as pure Java. In the test env I'm using directly Guice instead of GIN.
Setting up the tests I've issues providing to Guice a binding for the EventBinders because in normal env this is managed by code generators in GWT.
Have you never faced with the problem?

@gkdn

This comment has been minimized.

Show comment
Hide comment
@gkdn

gkdn Mar 11, 2014

Member

If there is no binding provided for a class, then GIN will create the instance for you via GWT.create. So you can inject your MyEventBinder and then let it automatically handed by GIN.
Then in your test code, you can use Guice and a mocking framework (e.g. mockito) to provide the testing instance for MyEventBinder.

Member

gkdn commented Mar 11, 2014

If there is no binding provided for a class, then GIN will create the instance for you via GWT.create. So you can inject your MyEventBinder and then let it automatically handed by GIN.
Then in your test code, you can use Guice and a mocking framework (e.g. mockito) to provide the testing instance for MyEventBinder.

@gkdn

This comment has been minimized.

Show comment
Hide comment
@gkdn

gkdn Mar 11, 2014

Member

@ekuefler: I remember that there was a reflection based implementation for EventBinder. I forgot why we didn't include it as part the open-source release. Do you remember?

Member

gkdn commented Mar 11, 2014

@ekuefler: I remember that there was a reflection based implementation for EventBinder. I forgot why we didn't include it as part the open-source release. Do you remember?

@fedy2

This comment has been minimized.

Show comment
Hide comment
@fedy2

fedy2 Mar 11, 2014

Thank you for your reply @gokdogan.
My idea was to use Mockito to replace the EventBinder implementation but I want to avoid to manually declare all the EventBinders in Guice configuration. The tests are integration tests and they include multiple components that declare an EventBinder.
The only solution that I've in mind is to use reflection in order to discover all the EventBinder extensions and then declare the bindings with a mock implementation in the Guice configuration.

fedy2 commented Mar 11, 2014

Thank you for your reply @gokdogan.
My idea was to use Mockito to replace the EventBinder implementation but I want to avoid to manually declare all the EventBinders in Guice configuration. The tests are integration tests and they include multiple components that declare an EventBinder.
The only solution that I've in mind is to use reflection in order to discover all the EventBinder extensions and then declare the bindings with a mock implementation in the Guice configuration.

@ekuefler

This comment has been minimized.

Show comment
Hide comment
@ekuefler

ekuefler Mar 17, 2014

Contributor

This is going to be tricky I think. You're basically trying to re-implement GWT.create using Guice. But each EventBinder is its own type and would have to be bound separately. I don't think Guice has any way to say "bind all subtypes of X like this", which is what you would need to get this working without having to explicitly list every EventBinder. It's also going to be hard to figure out reflectively, since Java doesn't have a way to list all subclasses of a given type.

You could probably get this to work using a FakeProvider from GwtMockito - in this case you would keep using GWT.create to create the EventBinder rather than injecting it. GwtMockito works by intercepting calls to GWT.create and allows you to intercept all calls for a supertype, so you could register a FakeProvider for EventBinder that would then be able to instantiate concrete subclasses of it. The implementation would be pretty similar to FakeUiBinderProvider. If you don't want to use GwtMockito you could also set up your own bridge to intercept calls to GWT.create.

I'm not sure if we had a specific reason for not including the reflective EventBinder, would probably be pretty easy to clean up and commit. It's also pretty trivial for people to write themselves.

Contributor

ekuefler commented Mar 17, 2014

This is going to be tricky I think. You're basically trying to re-implement GWT.create using Guice. But each EventBinder is its own type and would have to be bound separately. I don't think Guice has any way to say "bind all subtypes of X like this", which is what you would need to get this working without having to explicitly list every EventBinder. It's also going to be hard to figure out reflectively, since Java doesn't have a way to list all subclasses of a given type.

You could probably get this to work using a FakeProvider from GwtMockito - in this case you would keep using GWT.create to create the EventBinder rather than injecting it. GwtMockito works by intercepting calls to GWT.create and allows you to intercept all calls for a supertype, so you could register a FakeProvider for EventBinder that would then be able to instantiate concrete subclasses of it. The implementation would be pretty similar to FakeUiBinderProvider. If you don't want to use GwtMockito you could also set up your own bridge to intercept calls to GWT.create.

I'm not sure if we had a specific reason for not including the reflective EventBinder, would probably be pretty easy to clean up and commit. It's also pretty trivial for people to write themselves.

@tbroyer

This comment has been minimized.

Show comment
Hide comment
@tbroyer

tbroyer Mar 17, 2014

Contributor

This is going to be tricky I think. You're basically trying to re-implement GWT.create using Guice. But each EventBinder is its own type and would have to be bound separately. I don't think Guice has any way to say "bind all subtypes of X like this", which is what you would need to get this working without having to explicitly list every EventBinder.

It should be possible using Guice's SPI. But in the case of a test, I suppose one could live with an explicit binding, provided there's an existing reflective implementation of EventBinder.

@Provides MyEventBinder provideMyEventBinder() {
  return EventBinderSource.create(MyEventBinder.class);
}
Contributor

tbroyer commented Mar 17, 2014

This is going to be tricky I think. You're basically trying to re-implement GWT.create using Guice. But each EventBinder is its own type and would have to be bound separately. I don't think Guice has any way to say "bind all subtypes of X like this", which is what you would need to get this working without having to explicitly list every EventBinder.

It should be possible using Guice's SPI. But in the case of a test, I suppose one could live with an explicit binding, provided there's an existing reflective implementation of EventBinder.

@Provides MyEventBinder provideMyEventBinder() {
  return EventBinderSource.create(MyEventBinder.class);
}
@fedy2

This comment has been minimized.

Show comment
Hide comment
@fedy2

fedy2 Mar 17, 2014

@ekuefler
The FakeProvider from GwtMockito sounds like a nice solution, I will check on it.

@tbroyer
I've searched for a solution using Guice's SPI but with no fortune. Some tests, that are integration tests, involves many EventBinders and I want to a void an explicit binding.

So far I took the "by reflection" solution using the Reflections library (https://github.com/ronmamo/reflections) as support.
The reflections library scans the CP and finds all the EventBinder extensions.
For each extension the target class is analyzed in order to find all the methods to be binded to the event bus (it is the same work done by the EventBinder generator) and a GenericEventHandler is created.
Finally Guice is configured in order to bind the EventBinder extension to a mocked binder.
(Here the used code: https://github.com/cotrix/cotrixrep/blob/master/cotrix/cotrix-web/src/test/java/org/acme/util/EventBinderBindingsProvider.java)

I'm using a similar solution in order to bind the async services interfaces to their effective implementations (We want to run both client and server code in the same JVM), but that is another story.

Thank you all for the support.

fedy2 commented Mar 17, 2014

@ekuefler
The FakeProvider from GwtMockito sounds like a nice solution, I will check on it.

@tbroyer
I've searched for a solution using Guice's SPI but with no fortune. Some tests, that are integration tests, involves many EventBinders and I want to a void an explicit binding.

So far I took the "by reflection" solution using the Reflections library (https://github.com/ronmamo/reflections) as support.
The reflections library scans the CP and finds all the EventBinder extensions.
For each extension the target class is analyzed in order to find all the methods to be binded to the event bus (it is the same work done by the EventBinder generator) and a GenericEventHandler is created.
Finally Guice is configured in order to bind the EventBinder extension to a mocked binder.
(Here the used code: https://github.com/cotrix/cotrixrep/blob/master/cotrix/cotrix-web/src/test/java/org/acme/util/EventBinderBindingsProvider.java)

I'm using a similar solution in order to bind the async services interfaces to their effective implementations (We want to run both client and server code in the same JVM), but that is another story.

Thank you all for the support.

@klimeryk

This comment has been minimized.

Show comment
Hide comment
@klimeryk

klimeryk Aug 27, 2014

Hi all,
based on your comments and suggestions, I've come up with the following implementation of a FakeProvider for EventBinder: https://gist.github.com/klimeryk/e090756d9b95dd3bc6aa

It doesn't do much in terms of safe-guarding like checking if the event handler methods have the correct number of arguments, etc. - I'm assuming that EventBinderGenerator/Writer took care of that.
Hopefully this will help someone who stumbled upon this issue :)

klimeryk commented Aug 27, 2014

Hi all,
based on your comments and suggestions, I've come up with the following implementation of a FakeProvider for EventBinder: https://gist.github.com/klimeryk/e090756d9b95dd3bc6aa

It doesn't do much in terms of safe-guarding like checking if the event handler methods have the correct number of arguments, etc. - I'm assuming that EventBinderGenerator/Writer took care of that.
Hopefully this will help someone who stumbled upon this issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment