There is some interface called say called Foo
.
interface Foo {
void add(Object key, Object value);
Object get(Object key);
void someOtherMethodUnessentialToTesting();
}
There is an implementation in the test called MockFoo
that implements most methods in a "default" way (doing nothing, returning null
, basically only implementing them so it compiles). However, it implements a couple to give real functionality, and they are methods that insert and read from a Map
. (If the last bit wasn't essential I would just use a Mockito mock and wouldn't even be asking.)
// The current "bad mock"
class MockFoo implements Foo {
Map<Object, Object> map = new ...
@Override
void add(Object key, Object value) {
map.put(key, value);
}
@Override
Object get(Object key) {
map.get(key);
}
@Override
void someOtherMethodUnessentialToTesting()
{}
}
The problem is that because this is not a Mockito mock, every time the interface changes the test has to be updated. Yes, people should check better to fix all implementations of the interface they change, but there really shouldn't be an implementation in the test in the first place in my opinion.
I am confused on how to solve this. My instinct is to make it abstract and implement only those methods then mock it somehow so that it calls those "real" methods when it needs them. I read that Mockito has a thenDoRealMethod()
for stubs but this is only for returning values so it would not work on a void method.
// My abstract class I was trying to stub somehow
abstract class FooForTest implements Foo {
Map<Object, Object> map = new ...
@Override
void add(Object key, Object value) {
map.put(key, value);
}
@Override
Object get(Object key) {
map.get(key);
}
}
I realize this may be a design issue and adding in an AbstractFoo
in the real code is probably best (because the add and get won't change really) but I am more curious if there is a way to fix this once-and-for-all just by modifying the test code.