My Java project uses Spring. I have an interface Connector
that's implemented by several classes, ConnectorV1
, ConnectorV2
, and so on.
The classes are annotated @Component("V1")
, @Component("V2")
, and so on, to distinguish them. The classes are configured for request scope. For example:
@Component("V2")
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.INTERFACES)
public class ConnectorV2 implements Connector {
One of my integration test classes uses @Autowired @Qualifier("V2")
to obtain an instance of ConnectorV2
as classUnderTest
and test it. I lately found that I had accidentally wired the ConnectorV1
and received weird test results. I'd therefore like to double-check in one of the test methods that I really have the right class at hand.
Unfortunately, all my attempts to assert the concrete class of classUnderTest
failed because the instance at runtime is first of all a com.sun.proxy$Proxy{someNumber}
. Even flexible assertions like AssertJ's assertThat(classUnderTest).isInstanceOf(ConnectorV2.class)
fail to identify the actual class.
Is there a way to look beyond that proxy and see the "real" class that it encapsulates?
you can use AopProxyUtils.ultimateTargetClass(controller)
. Here is a simple example:
@SpringBootTest(classes = Question.ControllerV2.class)
public class Question {
@Component("V2")
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.INTERFACES)
static class ControllerV2 implements Controller {}
interface Controller {}
@Autowired
@Qualifier("V2")
private Controller controller;
@Test
void testInstanceOf() {
Class<?> clazz = AopProxyUtils.ultimateTargetClass(controller);
Assertions.assertThat(clazz).isEqualTo(ControllerV2.class);
}
}
Though, are you sure this is a good idea? This will couple the test to the implementation. The B.D.D. approach suggests testing the behavior and abstracting away the implementation details from the test - making refactoring easier.