Mock socket

Few months ago I have written a small tool that mocks network sockets in Java. Now I have some time to describe it, so here you are.

Let’s imagine you want to test network communication in Java. It’s not easy, you have to start some server on the other side, configure its responses and somehow verify that the data you send are correct.

With mock-socket it’s incredibly easy.

import static net.javacrumbs.mocksocket.MockSocket.*;
...

//prepare mock
byte[] dataToWrite = new byte[]{5,4,3,2};
expectCall().andReturn(emptyResponse());
	
//do test
Socket socket = SocketFactory.getDefault().createSocket("example.org", 1234);
IOUtils.write(dataToWrite, socket.getOutputStream());
socket.close();
	
//verify data sent
assertThat(recordedConnections().get(0), data(is(dataToWrite)));
assertThat(recordedConnections().get(0), address(is("example.org:1234")));

You see, just statically import MockSocket class, prepare the mock, execute the test and verify the data. The library just removes the default Java socket implementation and place a mock implementation in its stead.

Of course, this example does not have much sense. It just tests that Java socket implementation works. But imagine that you implement some non-trivial network library. A test library can be handy.

Moreover, there is a HTTP extension which can be used if you want to test some HTTP client. Let’s say a JSON REST client. In such case, you can write this.

import static net.javacrumbs.mocksocket.http.HttpMockSocket.*;

...

//prepare mock
expectCall()
  .andWhenRequest(uri(is("/test/something.do")))
     .thenReturn(response().withStatus(404))
  .andWhenRequest(uri(is("/test/other.do")))
    .thenReturn(response().withContent("Text")).thenReturn(response().withContent("Text"));

//do your test
...

//verify 
assertThat(recordedConnections(), hasItem(header("Accept", is("text/plain"))));		

Ain’t great? You can do much more, please take a look at the project page if you are interested.

Converting JSON to XML

I have been working on a validation tool that would allow us to validate JSON messages. I could not any usable JSON validator in Java so I have decided to use RelaxNG. It had one catch. RelaxNG is designed for XML validation, not JSON.

That’s the reason why I have decided to convert JSON to XML. Before we dive into the implementation, let’s think about the problem in general. Both JSON and XML ale tree structures and they are quite similar. In fact, I have discovered only the following differences.

  1. JSON supports multiple top-level elements. In XML we can have only one root element. While {“a”:1, “b”:2} is a valid JSON document, <a>1</a><b>2</b> is not valid XML.
  2. JSON supports arrays, XML does not.
  3. JSON has null keyword, in XML we several options how to deal with nulls. We can either represent it by an empty element or using xsi:nil attribute.
  4. JSON has support for boolean and numeric types. In JSON {“a”:1} has different meaning than {“a”:”1″} (with double quotes). It’s not possible to represent such difference in the XML.

All of the problems were acceptable for my needs. There would be more problems when going in the other direction, from XML to JSON, but I did not need it. The only thing I have needed was to convert from

{"root":{
	"data1":[
		[1,2,3], 				
        	[4,5,6]
	],
	"data2":null,
	"data3":"2011-05-30T10:00:00",
	"data4":
	{
		"a":1,
     		"b":2
	}
}
}

to

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<data1>
		<data1>
			<data1>1</data1>
			<data1>2</data1>
			<data1>3</data1>
		</data1>
		<data1>
			<data1>4</data1>
			<data1>5</data1>
			<data1>6</data1>
		</data1>
	</data1>
	<data2/>
	<data3>2011-05-30T10:00:00</data3>
	<data4>
		<a>1</a>
		<b>2</b>
	</data4>
</root>  

There already is a project Jettison, that is able to convert between JSON and XML but it does not handle JSON arrays properly. Moreover, I have encountered some bugs like this one. It’s trivial to fix but it’s there for more than half a year. Strange.

One nice Saturday morning I have decided to implement it. And I have found that it’s incredibly easy. It’s just matter of using Jackson pull parser and generating SAX events based on it. It’s about 200 lines of code that you can enjoy here here.

Feature branching

Před chvílí jsem dokoukal povídání Mika Masona a Martina Fowlera o dělání větví pro vlastnosti (feature branching). Do teď jsem si myslel, že to je dobrá věc, ale trochu mé přesvědčení zviklali.

O co jde? Některé týmy postupují tak, že pro každou novou vyvíjenou věc založí novou větev. Ta se začlení do hlavní vývojové větve, až když je daná věc hotová. Má to spoustu výhod a až dodnes mě nedošlo, že to s sebou nese i pár zásadních problémů. Pro nezkreslenou informaci se koukněte na to video, má jen jedenáct minut. Já tu shrnu jen to, co mi přišlo jako nejzásadnější.

Feature branching ohromně komplikuje refaktoring. Když si všimnete zatuchlého kódu, můžete ho refaktorovat, ale dost si tím zkomplikujete merge. Pokud totiž uděláte větší refaktoring, je velká šance, že se dotknete kódu, na kterém dělá někdo jiný. Dostanete se do situace, s kterou vám ani Git nepomůže. Strávíte pěkných pár chvilek ručním mergem a je tu pak dost velká pravděpodobnost, že příště si ten refaktoring dvakrát rozmyslíte. A to je špatně.

Když nad tím tak přemýšlím, potkalo mě to minulý týden. Udělal jsem ve své větvi refaktoring a začlenil jsem ho do hlavní větve. Kolega ale stále žil ve své větvi, mé geniální změny si proto nevšiml a svůj kód udělal o poznání hůře, než by mohl. Vůbec mě napadlo, že by to mohlo být způsobeno nějakou systematickou chybou.

Neříkám, že přestanu feature branching dělat, ale rozhodně se nad ním pořádně zamyslím.