package org.jooby.internal.mvc; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.isA; import java.util.List; import org.jooby.Mutant; import org.jooby.Request; import org.jooby.WebSocket; import org.jooby.WebSocket.CloseStatus; import org.jooby.test.MockUnit; import org.jooby.test.MockUnit.Block; import org.junit.Test; import com.google.common.collect.ImmutableList; import com.google.inject.Binder; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.TypeLiteral; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.util.Types; public class MvcWebSocketTest { public static class ImNotACallback { } @SuppressWarnings("rawtypes") public static class CallbackWithoutType implements WebSocket.OnMessage { @Override public void onMessage(final Object message) throws Exception { } } public static class StringSocket implements WebSocket.OnMessage<String> { @Override public void onMessage(final String message) throws Exception { } } public static class Pojo { } public static class PojoSocket implements WebSocket.OnMessage<Pojo> { @Override public void onMessage(final Pojo message) throws Exception { } } public static class PojoListSocket implements WebSocket.OnMessage<List<Pojo>> { @Override public void onMessage(final List<Pojo> message) throws Exception { } } public static class MySocket implements WebSocket.OnMessage<String>, WebSocket.OnClose, WebSocket.OnError, WebSocket.OnOpen { @Override public void onMessage(final String data) throws Exception { } @Override public void onOpen(final Request req, final WebSocket ws) throws Exception { } @Override public void onError(final Throwable err) { } @Override public void onClose(final CloseStatus status) throws Exception { } } @Test public void newInstance() throws Exception { new MockUnit(WebSocket.class, Injector.class, MySocket.class, Binder.class) .expect(childInjector(MySocket.class)) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), MySocket.class); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void onClose() throws Exception { new MockUnit(WebSocket.class, Injector.class, MySocket.class, Binder.class) .expect(childInjector(MySocket.class)) .expect(unit -> { unit.get(MySocket.class).onClose(WebSocket.NORMAL); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), MySocket.class).onClose(WebSocket.NORMAL); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void shouldIgnoreOnClose() throws Exception { new MockUnit(WebSocket.class, Injector.class, StringSocket.class, Binder.class) .expect(childInjector(StringSocket.class)) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), StringSocket.class).onClose(WebSocket.NORMAL); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void onStringMessage() throws Exception { new MockUnit(WebSocket.class, Injector.class, StringSocket.class, Binder.class, Mutant.class) .expect(childInjector(StringSocket.class)) .expect(mutant(TypeLiteral.get(String.class), "string")) .expect(unit -> { StringSocket socket = unit.get(StringSocket.class); socket.onMessage("string"); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), StringSocket.class) .onMessage(unit.get(Mutant.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void onPojoMessage() throws Exception { Pojo pojo = new Pojo(); new MockUnit(WebSocket.class, Injector.class, PojoSocket.class, Binder.class, Mutant.class) .expect(childInjector(PojoSocket.class)) .expect(mutant(TypeLiteral.get(Pojo.class), pojo)) .expect(unit -> { PojoSocket socket = unit.get(PojoSocket.class); socket.onMessage(pojo); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), PojoSocket.class) .onMessage(unit.get(Mutant.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void onListPojoMessage() throws Exception { Pojo pojo = new Pojo(); new MockUnit(WebSocket.class, Injector.class, PojoListSocket.class, Binder.class, Mutant.class) .expect(childInjector(PojoListSocket.class)) .expect(mutant(TypeLiteral.get(Types.listOf(Pojo.class)), ImmutableList.of(pojo))) .expect(unit -> { PojoListSocket socket = unit.get(PojoListSocket.class); socket.onMessage(ImmutableList.of(pojo)); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), PojoListSocket.class) .onMessage(unit.get(Mutant.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test(expected = IllegalArgumentException.class) public void messageTypeShouldFailOnWrongCallback() throws Exception { MvcWebSocket.messageType(ImNotACallback.class); } @Test(expected = IllegalArgumentException.class) public void messageTypeShouldFailOnCallbackWithoutType() throws Exception { MvcWebSocket.messageType(CallbackWithoutType.class); } @SuppressWarnings({"rawtypes", "unchecked" }) private <T> Block mutant(final TypeLiteral type, final T value) { return unit -> { Mutant mutant = unit.get(Mutant.class); expect(mutant.<T> to(type)).andReturn(value); }; } @Test public void onOpen() throws Exception { new MockUnit(Request.class, WebSocket.class, Injector.class, MySocket.class, Binder.class) .expect(childInjector(MySocket.class)) .expect(unit -> { unit.get(MySocket.class).onOpen(unit.get(Request.class), unit.get(WebSocket.class)); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), MySocket.class) .onOpen(unit.get(Request.class), unit.get(WebSocket.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void onError() throws Exception { new MockUnit(Throwable.class, WebSocket.class, Injector.class, MySocket.class, Binder.class) .expect(childInjector(MySocket.class)) .expect(unit -> { unit.get(MySocket.class).onError(unit.get(Throwable.class)); }) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), MySocket.class) .onError(unit.get(Throwable.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @Test public void shouldIgnoreOnError() throws Exception { new MockUnit(Throwable.class, WebSocket.class, Injector.class, StringSocket.class, Binder.class) .expect(childInjector(StringSocket.class)) .run(unit -> { new MvcWebSocket(unit.get(WebSocket.class), StringSocket.class) .onError(unit.get(Throwable.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @SuppressWarnings("unchecked") @Test public void newWebSocket() throws Exception { new MockUnit(Request.class, WebSocket.class, Injector.class, MySocket.class, Binder.class) .expect(unit -> { WebSocket ws = unit.get(WebSocket.class); MySocket mvc = unit.get(MySocket.class); mvc.onOpen(unit.get(Request.class), unit.get(WebSocket.class)); ws.onClose(isA(WebSocket.OnClose.class)); ws.onError(isA(WebSocket.OnError.class)); ws.onMessage(isA(WebSocket.OnMessage.class)); }) .expect(childInjector(MySocket.class)) .run(unit -> { MvcWebSocket.newWebSocket(MySocket.class) .onOpen(unit.get(Request.class), unit.get(WebSocket.class)); }, unit -> { unit.captured(Module.class).iterator().next().configure(unit.get(Binder.class)); }); } @SuppressWarnings({"rawtypes", "unchecked" }) private <T extends WebSocket.OnMessage> Block childInjector(final Class<T> class1) { return unit -> { Injector childInjector = unit.mock(Injector.class); T socket = unit.get(class1); expect(childInjector.getInstance(class1)).andReturn(socket); Injector injector = unit.get(Injector.class); expect(injector.createChildInjector(unit.capture(Module.class))).andReturn(childInjector); WebSocket ws = unit.get(WebSocket.class); expect(ws.require(Injector.class)).andReturn(injector); AnnotatedBindingBuilder<WebSocket> aabbws = unit.mock(AnnotatedBindingBuilder.class); aabbws.toInstance(ws); Binder binder = unit.get(Binder.class); expect(binder.bind(WebSocket.class)).andReturn(aabbws); }; } }