Pro jednoho z naších zákazníků dodáváme C2DM – zasílání notifikací na mobilní telefon s operačním systémem Android. Tato služba je implementována jako HTTP request, ve kterém pošlete zprávu, registrační identifikátor instance zařízení s androidem a C2DM server se postará o doručení.
Narazil jsem ale na problém jak vytvořit unit test, který ověří správný formát odesílané notifikace. Problém je právě v tom, jak namockovat chování C2DM serveru bez toho, abych musel někde rozbíhat Jetty či nedejbože Tomcat. Testovaný kód vypadá nějak takto:
private static int sendMessage(String message, URL url) throws IOException { // create connection HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setRequestMethod("POST"); // post data DataOutputStream output = new DataOutputStream(connection.getOutputStream()); output.writeBytes("message="message); output.flush(); output.close(); // establish connection connection.connect(); // return errocode return connection.getResponseCode(); }
Umím vytvořit mock interfacu (viz. EasyMock , PowerMock ect.), dokonce i stub konkrétní třídy. Final třídu
URL zkrátka nepodědíte a testovanému kódu pak „nepředhodíte“. Narazil jsem na knihovnu simple, která velice jednoduše na několika řádcích na pár sekund rozběhne „webový server“. Vy pak můžete snadno nasimulovat chování protějšího serveru. Vytvoříte třídu implementující interface org.simpleframework.http.core.Container
public class MockC2dmServer implements Container { protected String capturedMessage; public void handle(Request request, Response response) { try { capturedMessage = request.getParameter("message"); } catch (IOException e1) { capturedMessage = null; } if(capturedMessage != null) { response.setCode(HttpURLConnection.HTTP_OK); } else { response.setCode(HttpURLConnection.HTTP_BADREQUEST); } } }
Samotné vytvoření serveru a test pak může vypadat nějak takto:
@Test public void basicSenderTest() throws Exception { MockC2dmServer mockServer = new MockC2dmServer(); // binds server to socket on adress Connection connectionServer = new SocketConnection(mockServer); SocketAddress address = new InetSocketAddress("localhost", 8080)); connectionServer.connect(address); // test method String message = "message text"; C2dmNotificationSender.sendNotification(message, new URL("http://localhost:8080"); Assert.assertEquals(message, mockServer.capturedMessage); }
Uznávám, že tento způsob testování má svá rizika, například vám nikdo nezaručí, že port 8080 bude volný, to však jde minimalizovat například metodou, která vám nějaký volný port najde, ale to už není tématem tohoto článku. Pokud někdo z vás přijde na jiné, lepší řešení rád si ho přečtu v diskuzi pod článkem.
Zpět