GWTMockito UnsatisfiedLinkError

I have done most of my MVP test in GWT without validating widgets. I would like to be able to create more complex widgets and test them well without using GwtTestCase

(slow).

Out of curiosity, I tried a very simple test. Given a very simple widget, a bit like this (this is not my exact class, just a simplified example):

public class MyWidget extends Composite {
    private TextBox boxOne, boxTwo;

    public MyWidget() {
        boxOne = new TextBox();
        boxTwo = new TextBox();
        VerticalPanel panel = new VerticalPanel();
        panel.add( boxOne );
        panel.add( boxTwo );
        initWidget( panel );
    }

    public String[] getText() {
      return new String[] { boxOne.getText(), boxTwo.getText() }
    }
}

      

And I use the GWTMockito test a bit:

public class MyWidgetTest {

    private ConstantsWithLookup constants;
    private MyWidget widget;

    @Before
    public void createMocks() {
        GwtMockito.initMocks( this );
        constants = mock( ConstantsWithLookup.class );
    }

    @Test
    public void testIsInvalidByDefault() {
        widget = new MyWidget( constants ) {
            protected void initWidget(Widget w) {
                // Disarm for testing
              }
        };
        assertNotNull( widget );
    }

    @After
    public void tearDown() {
        GwtMockito.tearDown();
    }

}

      

I immediately get:

java.lang.UnsatisfiedLinkError: com.google.gwt.dom.client.Document.nativeGet()Lcom/google/gwt/dom/client/Document;
    at com.google.gwt.dom.client.Document.nativeGet(Native Method)
    at com.google.gwt.dom.client.Document.get(Document.java:46)
    at com.google.gwt.user.client.ui.TextBox.<init>(TextBox.java:78)
    at mypackage.MyWidget.<init>(MyWidget.java:linenumber)
    ... etc ...

      

You will notice that I am not using a test runner, I tried, but the project I tested is using JUnit 4.4, the test runner doesn't seem to work with JUnit 4.4. If I use GwtMockitoTestRunner I get:

java.lang.NoSuchFieldError: NULL
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:57)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
    at com.google.gwtmockito.GwtMockitoTestRunner.<init>(GwtMockitoTestRunner.java:114)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

      

Based on another Stack Overflow question , and also a quick investigation, I tend to believe it has something to do with the JUnit version used in this project. GwtMockito uses BlockJunit4ClassRunner

which is marked @since 4.5.

So - is this test what GWTMockito is supposed to help? I am completely new to GWTMockito, so this could easily be a simple misunderstanding, but I would like to understand.

Can I use GWTMockito to test complex widgets made from smaller widgets with Composite

/ IsWidget

? Didn't GWTMockito help me with this JSNI question or am I misunderstanding something? Is it just because I am not using a test runner?

+3


source to share


1 answer


As I see it, there are two possibilities:

  • You forgot to use the GwtMockito JUnit runner:

    @RunWith(GwtMockitoTestRunner.class)
    public class MyTest {
        // ...
    }
    
          

    You can set GwtMockito to an alternate path if you need a custom runner for something different.

  • You don't use GWT.create

    to create your widgets.

The first point is simple: this runner is required for GwtMockito to perform its "magic".

The second point needs some explanation: GwtMockito works using GWT Deferred Binding . This means that all the widgets you want to automatically mock GwtMockito must be created by calling GWT.create

. It's straight forward with UiBinder - internally, all the widgets defined in the UiBinder template are created with GWT.create

, so you don't need to change anything to use it with GwtMockito. But unless you are using UiBinder (or providing

your own widget instances), GwtMockito cannot work its magic unless you create your widgets with GWT.create

.

From the GwtMockito Documentation (emphasis mine):

GwtMockito solves this and other GWT-related testing problems by letting you call GWT.create from JUnit tests returns Mockito mocks .




Update

I can verify that as of JUnit 4.4, the runner is throwing the exception you mentioned. I opened a question in the GwtMockito tracker for this.

As far as the test itself is concerned, I managed to get it to work. As I mentioned earlier, GwtMockito works thanks to Deferred Binding. This means your widgets must be created with GWT.create

members. This is the GwtMockito "path" to your widget. If you just call it new TextBox()

, it won't be able to replace that with a mock.
If you change your MyWidget class to the following, it will pass the test (note the calls GWT.create

).

public class MyWidget extends Composite {
    private TextBox boxOne, boxTwo;

    public MyWidget() {
        boxOne = GWT.create(TextBox.class);
        boxTwo = GWT.create(TextBox.class);
        VerticalPanel panel = GWT.create(VerticalPanel.class);
        panel.add( boxOne );
        panel.add( boxTwo );
        initWidget( panel );
    }

    public String[] getText() {
        return new String[] { boxOne.getText(), boxTwo.getText() };
    }
}

      

Knowing this, there are several options:

  • always remember to create all the widgets in your composites with GWT.create

  • expose them as visible packages (as you do in UiBinder) and assign them to mocks (created from mock

    or GWT.create

    ) in your tests
  • switch to UiBinder; /

No, it seems too attractive, the former seems to be the best overall.

+2


source







All Articles