Skip to content

Commit 363d7d1

Browse files
committed
Fix #26 by allowing FakeProviders to be specified for RPC interfaces.
1 parent bcef428 commit 363d7d1

File tree

3 files changed

+150
-33
lines changed

3 files changed

+150
-33
lines changed

gwtmockito/src/main/java/com/google/gwtmockito/GwtMockito.java

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -288,36 +288,27 @@ private static class Bridge extends GWTBridge {
288288

289289
@Override
290290
@SuppressWarnings("unchecked") // safe since we check whether the type is assignable
291-
public <T> T create(Class<?> type) {
292-
// Handle RemoteServices specially - GWT.create'ing them should return the Async version
293-
if (RemoteService.class.isAssignableFrom(type)) {
294-
Class<?> asyncType;
295-
try {
296-
asyncType = Class.forName(type.getCanonicalName() + "Async");
297-
} catch (ClassNotFoundException e) {
298-
throw new IllegalArgumentException(
299-
type.getCanonicalName() + " does not have a corresponding async interface", e);
300-
}
301-
if (registeredMocks.containsKey(asyncType)) {
302-
return (T) registeredMocks.get(asyncType);
303-
} else {
304-
return (T) mock(asyncType);
305-
}
306-
}
291+
public <T> T create(Class<?> createdType) {
292+
// If we're creating a RemoteService, assume that the result of GWT.create is being assigned
293+
// to the async version of that service. Otherwise, assume it's being assigned to the same
294+
// type we're creating.
295+
Class<?> assignedType = RemoteService.class.isAssignableFrom(createdType)
296+
? getAsyncType((Class<? extends RemoteService>) createdType)
297+
: createdType;
307298

308-
// Otherwise, first check if we have a GwtMock for this exact type and use it if so.
309-
if (registeredMocks.containsKey(type)) {
310-
return (T) registeredMocks.get(type);
299+
// First check if we have a GwtMock for this exact being assigned to and use it if so.
300+
if (registeredMocks.containsKey(assignedType)) {
301+
return (T) registeredMocks.get(assignedType);
311302
}
312303

313-
// Next check if we have a fake provider that can provide a fake for this type.
314-
T fake = (T) getFakeFromProviderMap(type, registeredProviders);
304+
// Next check if we have a fake provider that can provide a fake for the type being created.
305+
T fake = (T) getFakeFromProviderMap(createdType, registeredProviders);
315306
if (fake != null) {
316307
return fake;
317308
}
318309

319-
// If nothing has been registered, just return a new mock object to avoid NPEs.
320-
return (T) mock(type, new ReturnsCustomMocks());
310+
// If nothing has been registered, just return a new mock for the type being assigned.
311+
return (T) mock(assignedType, new ReturnsCustomMocks());
321312
}
322313

323314
@Override
@@ -337,5 +328,18 @@ public void log(String message, Throwable e) {
337328
e.printStackTrace();
338329
}
339330
}
331+
332+
/** Returns the corresponding async service type for the given remote service type. */
333+
private Class<?> getAsyncType(Class<? extends RemoteService> type) {
334+
Class<?> asyncType;
335+
try {
336+
asyncType = Class.forName(type.getCanonicalName() + "Async");
337+
} catch (ClassNotFoundException e) {
338+
throw new IllegalArgumentException(
339+
type.getCanonicalName() + " does not have a corresponding async interface", e);
340+
}
341+
return asyncType;
342+
}
343+
340344
}
341345
}

gwtmockito/src/test/java/com/google/gwtmockito/rpc/GwtMockitoRpcTest.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.gwtmockito.AsyncAnswers.returnSuccess;
2020
import static org.mockito.Matchers.any;
2121
import static org.mockito.Mockito.doAnswer;
22+
import static org.mockito.Mockito.mock;
2223
import static org.mockito.Mockito.verify;
2324

2425
import com.google.gwt.core.shared.GWT;
@@ -27,7 +28,9 @@
2728
import com.google.gwt.user.client.ui.HasText;
2829
import com.google.gwt.user.client.ui.Label;
2930
import com.google.gwtmockito.GwtMock;
31+
import com.google.gwtmockito.GwtMockito;
3032
import com.google.gwtmockito.GwtMockitoTestRunner;
33+
import com.google.gwtmockito.fakes.FakeProvider;
3134

3235
import org.junit.Test;
3336
import org.junit.runner.RunWith;
@@ -78,46 +81,64 @@ public void onFailure(Throwable caught) {
7881
@GwtMock TestRemoteServiceAsync service;
7982

8083
@Test
81-
@SuppressWarnings("unchecked")
8284
public void shouldAllowStubbedRpcSuccess() throws Exception {
83-
doAnswer(returnSuccess("success!"))
84-
.when(service).doRpc(any(String.class), any(AsyncCallback.class));
85+
doAnswer(returnSuccess("success!")).when(service).doRpc(any(String.class), anyAsyncCallback());
8586

8687
MyWidget widget = new MyWidget();
8788

8889
verify(widget.message).setText("success!");
8990
}
9091

9192
@Test
92-
@SuppressWarnings("unchecked")
9393
public void shouldAllowStubbedRpcFailure() throws Exception {
9494
doAnswer(returnFailure(new IllegalArgumentException("error!")))
95-
.when(service).doRpc(any(String.class), any(AsyncCallback.class));
95+
.when(service).doRpc(any(String.class), anyAsyncCallback());
9696

9797
MyWidget widget = new MyWidget();
9898

9999
verify(widget.message).setText("error!");
100100
}
101101

102102
@Test
103-
@SuppressWarnings("unchecked")
104103
public void shouldAllowStubbedRpcSuccessWithoutArgs() throws Exception {
105-
doAnswer(returnSuccess("success!"))
106-
.when(service).doRpcWithoutArgs(any(AsyncCallback.class));
104+
doAnswer(returnSuccess("success!")).when(service).doRpcWithoutArgs(anyAsyncCallback());
107105

108106
MyWidgetWithoutArgs widget = new MyWidgetWithoutArgs();
109107

110108
verify(widget.message).setText("success!");
111109
}
112110

113111
@Test
114-
@SuppressWarnings("unchecked")
115112
public void shouldAllowStubbedRpcFailureWithoutArgs() throws Exception {
116113
doAnswer(returnFailure(new IllegalArgumentException("error!")))
117-
.when(service).doRpcWithoutArgs(any(AsyncCallback.class));
114+
.when(service).doRpcWithoutArgs(anyAsyncCallback());
118115

119116
MyWidgetWithoutArgs widget = new MyWidgetWithoutArgs();
120117

121118
verify(widget.message).setText("error!");
122119
}
120+
121+
@Test
122+
public void gwtMockShouldTakePriorityOverFakes() {
123+
doAnswer(returnSuccess("mocked")).when(service).doRpcWithoutArgs(anyAsyncCallback());
124+
125+
GwtMockito.useProviderForType(
126+
TestRemoteService.class,
127+
new FakeProvider<TestRemoteServiceAsync>() {
128+
@Override
129+
public TestRemoteServiceAsync getFake(Class<?> type) {
130+
TestRemoteServiceAsync mock = mock(TestRemoteServiceAsync.class);
131+
doAnswer(returnSuccess("faked")).when(mock).doRpcWithoutArgs(anyAsyncCallback());
132+
return mock;
133+
}
134+
});
135+
MyWidgetWithoutArgs widget = new MyWidgetWithoutArgs();
136+
137+
verify(widget.message).setText("mocked");
138+
}
139+
140+
@SuppressWarnings("unchecked")
141+
private AsyncCallback<String> anyAsyncCallback() {
142+
return any(AsyncCallback.class);
143+
}
123144
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2013 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.google.gwtmockito.rpc;
17+
18+
import static com.google.gwtmockito.AsyncAnswers.returnSuccess;
19+
import static org.mockito.Matchers.any;
20+
import static org.mockito.Matchers.anyString;
21+
import static org.mockito.Mockito.doAnswer;
22+
import static org.mockito.Mockito.mock;
23+
import static org.mockito.Mockito.never;
24+
import static org.mockito.Mockito.verify;
25+
26+
import com.google.gwt.core.shared.GWT;
27+
import com.google.gwt.uibinder.client.UiField;
28+
import com.google.gwt.user.client.rpc.AsyncCallback;
29+
import com.google.gwt.user.client.ui.HasText;
30+
import com.google.gwt.user.client.ui.Label;
31+
import com.google.gwtmockito.GwtMockito;
32+
import com.google.gwtmockito.GwtMockitoTestRunner;
33+
import com.google.gwtmockito.fakes.FakeProvider;
34+
35+
import org.junit.Test;
36+
import org.junit.runner.RunWith;
37+
38+
/**
39+
* Tests that GwtMockito works when mocking gwt-rpc RemoteServices without a corresponding
40+
* GwtMock-annoted field.
41+
*/
42+
@RunWith(GwtMockitoTestRunner.class)
43+
public class GwtMockitoRpcWithoutGwtMockTest {
44+
45+
private static class MyWidget {
46+
@UiField HasText message = GWT.create(Label.class);
47+
private final TestRemoteServiceAsync service = GWT.create(TestRemoteService.class);
48+
49+
MyWidget() {
50+
service.doRpcWithoutArgs(new AsyncCallback<String>() {
51+
@Override
52+
public void onSuccess(String result) {
53+
message.setText(result);
54+
}
55+
56+
@Override
57+
public void onFailure(Throwable caught) {
58+
message.setText(caught.getMessage());
59+
}
60+
});
61+
}
62+
}
63+
64+
@Test
65+
public void shouldNeverCallBackIfNoFake() throws Exception {
66+
MyWidget widget = new MyWidget();
67+
68+
verify(widget.message, never()).setText(anyString());
69+
}
70+
71+
@Test
72+
public void shouldUseFakeIfProvided() {
73+
GwtMockito.useProviderForType(
74+
TestRemoteService.class,
75+
new FakeProvider<TestRemoteServiceAsync>() {
76+
@Override
77+
public TestRemoteServiceAsync getFake(Class<?> type) {
78+
TestRemoteServiceAsync mock = mock(TestRemoteServiceAsync.class);
79+
doAnswer(returnSuccess("faked")).when(mock).doRpcWithoutArgs(anyAsyncCallback());
80+
return mock;
81+
}
82+
});
83+
MyWidget widget = new MyWidget();
84+
85+
verify(widget.message).setText("faked");
86+
}
87+
88+
@SuppressWarnings("unchecked")
89+
private AsyncCallback<String> anyAsyncCallback() {
90+
return any(AsyncCallback.class);
91+
}
92+
}

0 commit comments

Comments
 (0)