Class SpyProxy<T>

java.lang.Object
ru.vyarus.dropwizard.guice.test.spy.SpyProxy<T>
Type Parameters:
T - bean type
All Implemented Interfaces:
com.google.inject.Provider<T>, jakarta.inject.Provider<T>, org.aopalliance.aop.Advice, org.aopalliance.intercept.Interceptor, org.aopalliance.intercept.MethodInterceptor

public class SpyProxy<T> extends Object implements org.aopalliance.intercept.MethodInterceptor, com.google.inject.Provider<T>
AOP interceptor redirect calls from the real bean into spy object, which was created around the same real bean.

There is a chicken-egg problem: service binding can't be overridden (with spy instance), because spy requires service instance for construction. So, instead of replacing bean, we intercept bean calls. Actual spy object is created lazily just after injector creation. On the first call, AOP interceptor breaks the current aop chain (if other interceptors registered) and redirect calls to spy, which again calls the same service (including aop handler), but, this time, it processes normally.

  • Constructor Details

    • SpyProxy

      public SpyProxy(Class<T> type)
      Create proxy.
      Parameters:
      type - bean type
  • Method Details

    • withInitializer

      public final SpyProxy<T> withInitializer(Consumer<T> initializer)
      Actual spy object instance is created only on first bean access (after or in time of application startup). Normally, it is ok to wait for application startup, configure spy object and then run tests methods (using spy). But if spied bean is involved in application startup (called by some managed objects) then the only way to configure it is to apply modification just after spy instance creation.

      Might be called multiple times (for multiple initializers configuration).

      Parameters:
      initializer - spy object initializer
      Returns:
      proxy instance
    • setInstanceProvider

      public void setInstanceProvider(com.google.inject.Provider<T> instanceProvider)
      Delayed bean instance provider. Required because a proxy object created before guice modules processing (provider could be obtained from binder).
      Parameters:
      instanceProvider - bean instance provider, used to get bean instance for spying
    • getType

      public Class<T> getType()
      Returns:
      proxied bean type
    • getSpy

      public T getSpy()
      Returns:
      spy instance
    • get

      public T get()
      Alternative spy provider to use proxy as Provider<?>. Internally, this method is not used as it is hard to search usages for it.
      Specified by:
      get in interface com.google.inject.Provider<T>
      Specified by:
      get in interface jakarta.inject.Provider<T>
      Returns:
      spy instance
    • invoke

      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) throws Throwable
      Specified by:
      invoke in interface org.aopalliance.intercept.MethodInterceptor
      Throws:
      Throwable