Hi,
I know the issue of using interfaces in Lucene has been discussed a few times before. I'd like to bring that to the table once again, though, because I think all those discussions were missing an important point: unit testing.
Without coding to interfaces it gets quite complicated to test for calls being made to an IndexWriter, for example. Of course it's possible to subclass IndexWriter and intercept all relevant calls, it still remains being a PITA.
Consider the following JUnit test method for testing a hypothetical Foo.foo(IndexWriter, Document) method that does nothing more than IndexWriter.addDocument(doc):
public void testFoo() throws IOException { final List addedDocuments = new ArrayList();
Directory dir = new RAMDirectory(); Analyzer analyzer = new StandardAnalyzer(); IndexWriter writer = new IndexWriter(dir, analyzer, true) { public void addDocument(Document doc) throws IOException { super.addDocument(doc); addedDocuments.add(doc); } };
Document doc = new Document(); new Foo().foo(writer, doc);
assertEquals(1, addedDocuments.size()); assertSame(doc, addedDocuments.get(0)); }
As you can see, you have to go at relatively great lengths just to test for a single method call. You need to create a Directory for the IndexWriter, and the IndexWriter instance itself. The IndexWriter really adds the document to the directory. In addition to that, we're taking notes of the added documents, so we can assert those later on.
This complexity even grows when doing other this: Say you want to test a call to IndexReader. The problem is that IndexReader.open() needs to have a valid index lying around. So to set up the environment for that requirement you first need to create a fake index in a RAMDirectory using an IndexWriter, then use that index to test IndexReader calls.
Now this is the same test method as above, but this time using EasyMock and an interface IIndexWriter (which IndexWriter hypothetically implements):
public void testFoo() throws IOException { MockControl writerControl = MockControl.createControl(IIndexWriter.class); IIndexWriter writer = (IIndexWriter) writerControl.getMock();
Document doc = new Document();
writer.addDocument(doc); writerControl.setVoidCallable();
writerControl.replay();
new Foo().foo(writer, doc);
writerControl.verify(); }
This time, it's all straightforward: No Directory created, no IndexWriter created, no document added. We just tell the mocked-up IndexWriter what method calls to expect and what to return (or do nothing, or throw an exception). Also there's no taking notes of added documents because EasyMock does that already.
The net benefit is that there are no useless objects created. Those could even harm the test results in the worst case. Also the test should run faster now, which can really add up when you have hundreds or thousands of tests.
-- Maik Schreiber * http://www.blizzy.de
GPG public key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x1F11D713 Key fingerprint: CF19 AFCE 6E3D 5443 9599 18B5 5640 1F11 D713
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]