The following classes reference each other crating a circular dependency:
@AllArgsConstructor
@Component
public class A {
private B b;
public String doSomething() {
return "Result: " + b.doSomethingElse();
}
}
@Componenet
public class B {
private A a;
@Autowired
public B(@Lazy final A a) {
this.a = a;
}
public String doSomethingElse() {
return a.toString();
}
}
I need to test class A
and make sure the actual implementation of class B
gets invoked:
@RunWith(MockitoJUnitRunner.class)
public class ATest {
@InjectMocks
private A a;
@Spy
private B b;
@Test
public void testDoSomething() {
final String result = a.doSomething();
assertNotNull(result);
}
}
@Spy
doesn't work and I always get the following error:
Unable to initialize @Spy annotated field 'b'.
Please ensure that the type 'B' has a no-arg constructor.
org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'b'.
Please ensure that the type 'B' has a no-arg constructor.
I could use @Mock
... but then I need to mock the expected result, whereas I need to invoke the actual implementation (that's why I'm using @Spy
).
Is there any way to workaround this? Thank you very much :-)
Do what Spring would do for a
@Lazy
dependency: don't inject the dependency directly, but a proxy instance which allows setting the dependency lazily. You can avoid some problems by depending on interfaces and not concrete classes.Better yet: don't write code with circular dependencies.