On Sunday, October 5, 2003, at 04:56 PM, Mike Hogan wrote:
Setting up an interface as you suggest is what I did, and I create mock
impls of that as I need in other test cases. But I also want to unit test
the _implementation_ itself? Here is the full code of the implementation:

Ok, so let's say you can subclass IndexWriter (which you can with the current codebase). How would this change what you have below?


public class LuceneSearchService implements SearchService {
    private static final String INDEX_FILE_PATH = "index";

This is something you'd need to change, I'd assume. Perhaps put in some kind of DirectoryFactory - and return a RAMDirectory or FSDirectory??


I don't see what a MockIndexWriter would do.

            writer = new IndexWriter(INDEX_FILE_PATH, new
StandardAnalyzer(), !indexExists());

Because you'd need to change this somehow.


//This is impossible to unit test as Hits is final, and the constructor
is package protected
public int search(final String query, int beginIndex, final int
endIndex, final List collector) throws SearchService.Exception {


I don't understand your comment here. Show me how you'd like to phrase the test if package permissions would let you.

You aren't passing Hits back out from here, what good would it do to mock it?

You are right that this code as it currently stands cannot be unit tested
using mock-objects. Thats because I tried to do so, ran into the final
problem, then rolled back. I will show you roughly how the code looked when
I refactored it to be mock-ready:

Ah, ok, so forget what I said above....


public class LuceneSearchService implements SearchService {
    private static final String INDEX_FILE_PATH = "index";
    private Context context = new DefaultContext();

    public void setContext(Context c) {
        this.context = c;
    }

public void index(String componentId, String componentDescription) throws
SearchService.Exception {
IndexWriter writer = null;
try {
writer = context.createIndexWriter(INDEX_FILE_PATH, new
StandardAnalyzer(), !indexExists());

Take this a step further, and have a createDirectory instead, that can return a RAMDirectory. Forget about a MockIndexWriter. Trust me :)


public static interface Context {
IndexWriter createIndexWriter(String path, Analyzer a, boolean create);
}

Don't lock yourself into a file system index. Please. You might want it in RAM one day :) (like in your unit tests)


I don't know if you see any value in that, but I do. I cannot do it because
IndexWriter is final and I cannot create a MockIndexWriter. I can do a
RAMDirectory and use the real Lucene API, but I find that less convenient
than the above. Do you not agree?

You just aren't seeing the forest from the trees here. You need to refactor and just let IndexWriter be internal and not mocked, but how you get at a Directory be flexible for testing. Even if you always use a file system directory even for testing, I highly recommend you bind to abstractions not concreteness. Bind to Directory, not IndexWriter as your "interface".


Erik


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to