Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write unit tests for an interface or each implementation?

I have a Java interface and a couple of implementations for it. Now I want to write unit test cases using Mockito.

My question is, should I write mock test cases each implementation or mock test cases only for interface? What is the best practice in this scenario? I hope my question makes sense. Please correct me, if I am missing something.

Classes Details:

interface MessageQueue {
    add()
    poll()
    size()
}

class InMemoryMessageQueue implements MessageQueue {
    add() {
        //implementation
    }
    poll() {
        //implementation
    }
    size() {
        //implementation
    }
}

class FileSystemMessageQueue implements MessageQueue {
    add() {
        //implementation
    }
    poll() {
        //implementation
    }
    size() {
        //implementation
    }
}

Currently I have Unit test cases only for MessageQueue interface using Mockito.

like image 993
stallapp Avatar asked Jan 04 '23 13:01

stallapp


2 Answers

It sounds like you are confusing a few details here, because the word "mock test case" doesn't make much sense without further details...

First of all, if you have, let's say, three implementations of your interface, best practice would be to test all three of these.

As long as your implementations don't have dependencies, no mocking is involved at all, because...

second, mocking is used in testing for dependencies. For example:

Your implementation #2 has to load data from the database. For this, it uses an instance of a class, let's call it DatabaseAccessor. By calling methods of this DatabaseAccessor object, it gets data from the database.

Now, if you want to unit test implementation #2, you don't want to actually need a database for that, because you get a whole lot of problems with that. For example, if the database is down or in an incorrect state, your test fails, even if the implementation #2, which is what you actually want to test, is perfectly fine.

And that's where mocking comes in. Instead of using an actual DatabaseAccessor object, you mock one. In other words, you create an object that looks like a DatabaseAccessor but doesn't actually accesses the Ddtabase. The behavior of such a mock can be configured, so that if, for example, a method is called, the mock returns some useful test data (again, without actually calling the database, you just tell it to "if method X is called, do this").

This way, you can concentrate on only testing your unit - implementation #2 - without having to worry about all it's dependencies. These are mocked and you know, they will behave as they should.

And yes, with Mockito you can mock both implementations and interfaces, but best practice is to work with interfaces anyway. For further questions, I suggest giving more details about your classes.

like image 81
Florian Schaetz Avatar answered Jan 06 '23 03:01

Florian Schaetz


Lets shift to a more object oriented discussion. Suppose we write a Car interface it has a method as putFuel something like,

interface Car {
    void putFuel(FuelStation fs);
}

Now I come up with three version of cars -PetrolCar implements Car -DieselCar implements Car -CNGCar implements Car

Now the putFuel() method will be very different for each of the implementation,such as Petrol Station,Diesel Station and CNG Station and so as their mocking related dependencies.

Therefore, I should write test cases for all the implementations as every implementation is different. Also consider that in future all implementations may have further different methods which the interface may not have, so it perfectly makes sense to write separate unit test cases for each of the implementations.

like image 44
penguin Avatar answered Jan 06 '23 02:01

penguin