Mocking a class vs. mocking its interface - java

For a unit test, I need to mock several dependencies. One of the dependencies is a class which implements an interface:
public class DataAccessImpl implements DataAccess {
...
}
I need to set up a mock object of this class which returns some specified values when provided with some specified parameters.
Now, what I'm not sure of, is if it's better to mock the interface or the class, i.e.
DataAccess client = mock(DataAccess.class);
vs.
DataAccess client = mock(DataAccessImpl.class);
Does it make any difference in regard to testing? What would be the preferred approach?

It may not make much difference in your case but the preferred approach is to mock interface, as normally if you follow TDD (Test Driven Development) then you could write your unit tests even before you write your implementation classes. Thus even if you did not have concrete class DataAccessImpl, you could still write unit tests using your interface DataAccess.
Moreover mocking frameworks have limitations in mocking classes, and some frameworks only mock interfaces by default.

In most cases technically there is no difference and you may mock as class so an interface. Conceptually it is better to use interfaces because of better abstraction.

It depends. If your code depends on the class and not on the interface you must mock the class to write a valid unit test.

You should mock the interface since it will help ensure you are adhering to Liskov Substitution Principal (https://stackoverflow.com/a/56904/3571100).

If you only use it through interface and it's not a partial mock, there is no difference other than your inner feeling. Mocking the class will also mock non-used public method if the class has them, but that is not a big deal to consider.

Related

Is there a way to prevent coupling between unit tests and tested classes

I have been using unit tests for quite a while. And I have a concern.
Assume I have an interface and one implementation
public interface UserDAO() {
public User getById(int id);
}
public class UserDAOJdbc implements UserDAO {
private CoolDataSource datasource; //Dependency injection
public User getById(int id) {
User user = this.dataSource.executeSQL("SELECT ....")
return user;
}
}
It is fairly easy to test UserDAOJdbc, just need to inject the dataSource object and replace it with a mock, the problem however is
This makes it difficult to write first the test and then the implementation, as before having the implementation I do not know how a particular UserDAO implementation is gonna work.
It makes test and implementation completely coupled, I am not sure if this is avoidable at all, but does not feel good.
In the case of an object that uses several objects to accomplish a task, mocking it becames a little bit harder, not to speak about changes.
Is there an effective way to prevent this? Is mocking a bad approach for some scenarios?
A unit test always tests an implementation. There's no point in testing interfaces. If you have more than one implementation of UserDAO you need to write more than one test.
I would respectfully disagree with BetaRide and suggest to test against interfaces. Different classes implementing the same interface would have the same functionality signature, implemented in a different way.
Therefore, you could write the whole test before implementation. This makes TDD evitable.
The tests would be abstract enough to be reused for other interface implementations. You could achieve reusability but that also depends on your testing framework.
You would have a more maintainable test code base
This would lead you to a better design. This is a subjective conclusion but it is my opinion that you are forced to make a more generic design when you write tests against interfaces before writing the actual implementation.
For example, lets suppose that you have an IRepository interface and two implementations DatabaseRepository and FilesRepository which implement the IRepository. If you test against the IRepository , this test could be reused among both FilesRepository and DatabaseRepository implementations. Moreover, the test could be written by the programmer writing the interface, before any of the implementation classes ready.
Hope I helped!
In case of unit testing the DAO you can use a Derby or some other small database that can embed into your application. You can actually create an entity manager factory and keep it ready in the setup method. The other methods can use it. Its not a pure unit test but helps you test easily.
A possible way to go about your problem :
Develop your application from the outside in. Imagine the dependencies your current object under test needs, but don't create concrete implementations for them yet. Just reason about operations and create interfaces with the appropriate method signatures. Mock these interfaces in your test.
Once the test passes, pick one of these interfaces. Create an abstract base test class and put general tests for all future implementations of the interface there. This is the contract of your interface, that all implementors must respect. For instance :
// High level, implementation-decoupled contract test
public abstract class UserDAOTest {
protected abstract UserDAO getSut();
protected abstract void insertUser(User user);
#Test
public void userFoundReturnsUser() {
User expectedUser = new User(1);
insertUser(expectedUser);
assertEquals(expectedUser, getSut().getById(1));
}
#Test
public void userNotFoundReturnsNull() {
assertNull(getSut().getById(123));
}
#Test (expected=Exception.class)
public void negativeIdthrowsException() {
GetSut().getById(-2);
}
}
Create as many test subclasses as you need implementations of the interface in your system. In each one, override the abstract test utility methods defined above to provide implementation-specific details. JUnit and other test frameworks will automatically run all tests from the base class for each derivative. Add any implementation-specific tests you may want.
Implement the concrete class, making the tests pass.
Jump to the next interface. Repeat.

Extending a class with final attributes. Mockup

I usually set each attribute of a class as final (only for attributes that will be initialized within the constructor).
The point is that I am now implementing a Mockup of an object for testing purpose. This Mockup extends the class that it is mocking up and this class has some final attributes. Therefore I'm forced to call the super() constructor within the constructor of the Mockup object. This breaks however the utility of the Mockup because I don't want it to initialize all of the attributes in the way the normal class does it. I'd rather call the Mockup constructor without calling to super() and doing whatever I want.
My question is: Is it a good practice to define attributes as final as long as they will force you to call the class constructor in the Mockup?
EDIT: I add some code. The problem in this case is that I'm using a singleton, I know that this is not a good idea when testing but in this case I cannot change it. So my intention is not to call this method in the Mockup.
public class ReportsDataManager {
private final Map<String, List<String>> translations;
public ReportsDataManager() {
this.translations = GenericUtils.getTranslation();
}
}
Declaring attributes final is a very good practice when you can do it. It confers immutability - guaranteed thread safety. Breaking it to mock is a bad idea. Your design should serve the user's needs, not your testing convenience.
If you wish to mock the class, give it an interface and mock the interface. Also, mocks aren't stubs. It sounds like you're creating a stub, rather than a mock.
If you do wish to create a mock, pick a library that generates mocks for interfaces for you.
In general I'd say that if a practice you use makes testing your code more difficult then the practice may be a smell.
Try to decide exactly what you want to achieve by setting variables final. Would protected be acceptable?
You can sidestep the final restriction with standard reflection. Since you are in the context of a mockup, this wouldn't cause much problems, I suppose. Just beware of multithreading issues: the JVM will assume the field adheres to the final semantics and will optimize with that in mind.

Reusing test implementations in JUnit 4?

I have an interface, e.g.:
public interface Thing {
FrobResult frob(FrobInput);
}
And several implementations of that interface (e.g. NormalThing, ImmutableThing, AsyncThing) that I am trying to test.
Many of my test methods are really about ensuring that the interface is implemented correctly, and thus are duplicated across each Thing implementation. In JUnit 3 a common solution to this would be to create a base class (extending TestCase) that is then subclassed by each implementation class. But is this the correct approach for JUnit 4?
Possible alternatives in (I believe) ascending order of preference:
Cut'n'paste the duplicated test methods. Not DRY at all, but I guess less worrisome in tests than it would be in production code.
Create an abstract class with #Test methods, and subclass it for each implementation test class. (Commonly seen with JUnit 3 tests -- is this still a good way to go in JUnit 4?)
Put the common test methods into a helper class, and invoke it on each implementation. (Composition instead of inheritance.)
What's the best practice for doing #3? Maybe a #RunWith(Parameterized.class) test that is parameterized with each implementation? Or is there a better way to accomplish this?
Yes, it is the correct approach to create a base class that is then subclassed by each implementation class in JUnit4, too.
I prefer the base test class for the interface to be abstract, i.e. your "alternative" 2, since I have made good experience in mimicing the inheritance hierarchy from the production code for the test code. So if you have interface I and implementations S1, S2 and S3, you make the abstract test class TestI and the test classes TestS1, TestS2 and TestS3.
Test cases should be speaking, i.e. tell a story. By choosing -- as always -- method names carefully and use clean behavioral subtyping only, inheritance does not obfuscate this.
I use #2 approach for JUnit and TestNG test cases. This is most convenient and easy to maintain. Its also straight forward to pick up (since its native to OOD to have base class that has common methods).
To me unit test classes are no different than regular project classes...so I do apply similar design considerations.

Mock a superclass constructor

I would like to know if I can mock a super class constructors call and its super() calls.
For example, I have the following classes
class A
{
A(..)
{
super(..)
}
}
class B extends A
{
B(C c)
{
super(c)
}
}
So, I am planning to unit test some methods in class B, but when creating an instance it does call the super class constructors making it tough to write unit tests. So, how can I mock all the super class constructor calls. Also I would like to mock few methods in class A so that it does return few values as I need.
Thanks!!
You could use PowerMock library. It is really a lifesaver when you need to accomplish things like yours.
https://github.com/powermock/powermock/wiki/Suppress-Unwanted-Behavior
Mocking a constructor is a very bad idea. Doing so is circumventing behavior that will happen in production. This is why doing work in the constructor, such as starting threads and invoking external dependencies, is a design flaw.
Can you honestly say that the work performed in the constructor has no effect on the behavior you're trying to test? If the answer is no, you run the risk of writing a test that will pass in a test environment, but fail in production. If the answer is yes, that is a plain case for moving that "work" outside the constructor. Another alternative is to move the behavior you're trying to test to another class (maybe it's own).
This is even more true if you're using a DI framework like Guice (which I assume because you tagged it that way).
The short answer to your question is "not exactly." You can't 'mock' a constructor, let alone a super. Also mocking super.anyMethod is difficult or impossible with mocking frameworks I'm familiar with. Powermock does allow you to suppress super constructors and problematic methods, which isn't quite the same as mocking them, but could help.
When B extends A, it is of course completely coupled with A. That's not a problem per se but it can be and it looks like it is here. Instead of having B extend A, try having B contain an A instead (and perhaps implement the same interface if necessary). Then you can inject a mock A and delegate all of the calls that you want. That would be much easier to unit test, no?
It's one of the benefits of test driven development that you discover these things in your design during testing.

Inject Util Class with Google Guice vs static Methods?

I'm wondering if it is a good style to inject utility methods with google guice.
Let's say we have a Converter Utility Class:
public class UtilClass
{
public static Result convert(Source src)
{
//Do conversion
return result;
}
}
My idea is to use guice to inject this Utility as Singleton like this
#Singleton
public class UtilClass
{
public Result convert(Source src)
{
//Do conversion
return result;
}
}
Which way is recommended for an Application built with guice?
It depends on the nature of your convert() method.
If it's something
simple
deterministic (i.e. doesn't depend on additional parameters)
have no side effects
is unlikely to change
etc
you can keep it as a static utility method.
Otherwise it's a good candidate for dependecy injection (you can rename it to ConversionService to make it more clear).
First of all, what is your goal in injecting an instance of this utility class rather than continuing to use the static method you have? Functions with input and output and no side effects are often best as static methods. That said, maybe you want to be able to change what this method does for testing or some such. In that case, you'd generally want to have the class implement some interface that you use in client classes.
At any rate, if UtilClass is stateless I'd just inject it not as a singleton. Injecting a non-singleton is faster than injecting a singleton. Maybe if you're going to be storing the injected instance in lots of other classes, a singleton might make sense to save space.
Personally I typically try to not let the fact my application is wired using a dependency injection framework influence the design decisions I make for my classes etc. Good design practices should dictate that. In your case it would seem your utility class has no dependency on state therefore it seems a sensible candidate to remain as static.
Regardless of this, your utility class is not an implementation of any interface so the client code using it still has a tightly coupled dependency. With this it is difficult to see what is the benefit of using DI to inject the utility class at all, as opposed to just referencing the static class directly in your client code.

Categories

Resources