I am writing Junits for some legacy code, I realized that when I mock my dependencies using @Mock annotation, some mocked objects seem to have a mockito interceptor associated with them, and some do not. I lack basics in computer programming, any help is appreciated.
//Did not work, because of lack of @InkectMocks,
//see that I create a new object of class to test.
public class foo {
ClassInTest classInTest;
AutoCloseable mocks;
@Mock
Animal animal;
@Mock
Bike vehicle;
@Before
public void init() {
mocks = openMocks(this);
classInTest = new ClassInTest();
}
@After
public void teardown() throws Exception {
mocks.close();
}
@Test
public void dogRidesBikeTest() {
classInTest.checkIfAnimalRidesVehicle(new Dog(), new Bike());
}
}
public interface Animal {
public String getName();
public String doSomething();
}
public class Dog implements Animal {
@Override
public String getName() {
return "Dog";
}
@Override
public String doSomething() {
return "Did something";
}
}
public interface Vehicle {
public String getName();
public String doSomething();
}
public class Bike implements Vehicle {
@Override
public String getName() {
return "Bike";
}
@Override
public String doSomething() {
return "Did something";
}
}
public class ClassInTest {
public boolean checkIfAnimalRidesVehicle(Animal animal, Vehicle vehicle) {
vehicle.doSomething();
remoteMagic(animal, vehicle);
return false;//dogs don't ride bikes!
}
public void remoteMagic(Animal animal, Vehicle vehicle) {
//magic magic magic
}
}
//This is an example of code that works,
//in line with @Lesiak's answer, the lack of a $MockitoMock$
//definition on a mock object should not stop you from being able
//to stub methods/interact with that mock in any way.
public class FooBarTest {
@InjectMocks
FooBar fooBar;
@Mock
List<String> mockList;
@Mock
CosmosAsyncContainer mockAsyncContainer;
@Mock
CosmosContainerResponse mockCosmosContainerResponse;
AutoCloseable autoCloseable;
@Before
public void setup() {
autoCloseable = openMocks(this);
}
@After
public void tearDown() throws Exception {
autoCloseable.close();
}
@Test
public void test() {
Mono<CosmosContainerResponse> raft = Mono.just(mockCosmosContainerResponse);
when(mockList.size()).thenReturn(3);
when(mockAsyncContainer.read()).thenReturn(raft);
var result = fooBar.helloWorld();
verify(mockList).size();
verify(mockAsyncContainer).read();
assertEquals(result, raft);
}
}
public class FooBar {
List<String> goodList;
CosmosAsyncContainer goodContainer;
public Mono<CosmosContainerResponse> helloWorld() {
assertEquals(3, goodList.size());
Mono<CosmosContainerResponse> raft;
try {
raft = goodContainer.read();
} catch (Exception ex) {
raft = Mono.empty();
System.out.println("gotcha!!");
}
return raft;
}
}
Is the difference that I am mocking an interface with the mockSomething(this is the one that has an interceptor associated with it), and a class with the mockSomethingElse(this is the one that DOES NOT an interceptor associated with it) objects?
When I put a debug point on the test "dogRidesBikeTest" and observe the objects created in the test context so far, I observe that one of these objects has a mockito interceptor on it, and the other does not.
Should the absence of an interceptor impact method stubbing(I would expect it to), and if yes, how do I work around this.
edit:
You are using mockito-inline, it changes the way the mocks are constructed:
This alternative mock maker which uses a combination of both Java instrumentation API and sub-classing rather than creating a new class to represent a mock.
InlineByteBuddyMockMaker javadoc says:
This mock maker will make a best effort to avoid subclass creation when creating a mock. Otherwise it will use the
org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker
to create the mock class. That means that the following condition is trueclass Foo { } assert mock(Foo.class).getClass() == Foo.class;
unless any of the following conditions is met, in such case the mock maker fall backs to the the creation of a subclass.
- the type to mock is an abstract class.
- the mock is set to require additional interfaces.
- the mock is explicitly set to support serialization
In your code:
Both mocks are fully functional (stubbing works etc), but the difference can be detected, as you already noticed.
Also, note that you dont pass the mocks to class under test - is that intrntional?