protected void prepareWriter(ClassReader cr, ClassLoader classLoader, boolean enhancedExceptionSensor, MethodInstrumentationConfig... configs) { classWriter = new LoaderAwareClassWriter(cr, ClassWriter.COMPUTE_FRAMES, classLoader); classInstrumenter = new ClassInstrumenter(instrumenterFactory, classWriter, Arrays.asList(configs), enhancedExceptionSensor); }
@Test public void exceptionThrowerIsInstrumentedWhenConstructor() throws Exception { Object[] params = { "test" }; long constructorId = 11L; when(sip.getId()).thenReturn(constructorId); prepareConfigurationMockConstructor(config, InstrumentationExceptionTestClass.class, false, String.class); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(EXCEPTION_TEST_CLASS_FQN); prepareWriter(cr, null, true, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); Class<?> clazz = createClass(EXCEPTION_TEST_CLASS_FQN, b); Constructor<?> constructor = clazz.getConstructor(new Class[] { String.class }); Object instance = constructor.newInstance(params); verify(hookDispatcher).dispatchConstructorBeforeBody(constructorId, params); verify(hookDispatcher).dispatchConstructorAfterBody(constructorId, instance, params); ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class); verify(hookDispatcher).dispatchConstructorBeforeCatch(eq(constructorId), captor.capture()); assertThat(captor.getValue().getClass().getName(), is(equalTo(MyTestException.class.getName()))); verifyNoMoreInteractions(hookDispatcher); }
/** * If method should be instrumented. If there is appropriate {@link MethodInstrumentationConfig} * that denotes that method should be instrumented this will be removed from the * {@link #instrumentationConfigs} and returned as a result. * * @param name * Name of the method. * @param desc * ASM description of the method. * @return {@link MethodInstrumentationConfig} if method should be instrumented, otherwise * <code>null</code> */ private MethodInstrumentationConfig shouldInstrument(String name, String desc) { for (Iterator<MethodInstrumentationConfig> it = instrumentationConfigs.iterator(); it.hasNext();) { MethodInstrumentationConfig config = it.next(); if (matches(name, desc, config)) { it.remove(); return config; } } return null; }
ClassInstrumenter classInstrumenter = new ClassInstrumenter(instrumenterFactory, classWriter, instrumentationConfigs, configurationStorage.isEnhancedExceptionSensorActivated()); classReader.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); if (classInstrumenter.isByteCodeAdded()) { Map<Long, long[]> methodToSensorMap = new HashMap<Long, long[]>(0); for (MethodInstrumentationConfig config : classInstrumenter.getAppliedInstrumentationConfigs()) { RegisteredSensorConfig registeredSensorConfig = createRegisteredSensorConfig(config); if (null != registeredSensorConfig) {
/** * {@inheritDoc} */ @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { // calling super to ensure the visitor pattern MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); MethodInstrumentationConfig instrumentationConfig = shouldInstrument(name, desc); if (null != instrumentationConfig) { // using JSR inliner adapter in order to remove JSR/RET instructions // see http://mail-archive.ow2.org/asm/2008-11/msg00008.html // using only if we add byte code methodVisitor = new JSRInlinerAdapter(methodVisitor, access, name, desc, signature, exceptions); // go over all instrumentation points and create the method visitor for (IMethodInstrumentationPoint instrumentationPoint : instrumentationConfig.getAllInstrumentationPoints()) { // note that here we create a chain of method visitor by passing the current one to // the one being created, thus following the visitor pattern of ASM MethodVisitor mv = instrumenterFactory.getMethodVisitor(instrumentationPoint, methodVisitor, access, name, desc, enhancedExceptionSensor); // safety for the null returned method visitor if (null != mv) { methodVisitor = mv; } } // add to list so that we know which are applied appliedInstrumentationConfigs.add(instrumentationConfig); } return methodVisitor; }
@Test public void constructorUnexpectedExceptionNotTrowingNoEnhanced() throws Exception { Object[] parameters = { "test" }; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false, Object.class); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); Class<?> clazz = createClass(TEST_CLASS_FQN, b); Constructor<?> constructor = clazz.getConstructor(new Class[] { Object.class }); try { constructor.newInstance(parameters); } catch (Throwable t) { } verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, parameters); ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class); verify(hookDispatcher).dispatchConstructorAfterBody(eq(methodId), captor.capture(), eq(parameters)); assertThat(captor.getValue().getClass().getName(), is(TEST_CLASS_FQN)); verifyNoMoreInteractions(hookDispatcher); }
protected void prepareWriter(ClassReader cr, ClassLoader classLoader, boolean enhancedExceptionSensor, MethodInstrumentationConfig... configs) { classWriter = new LoaderAwareClassWriter(cr, ClassWriter.COMPUTE_FRAMES, classLoader); classInstrumenter = new ClassInstrumenter(instrumenterFactory, classWriter, Arrays.asList(configs), enhancedExceptionSensor); }
@Test public void constructorUnexpectedExceptionTrowingNoEnhanced() throws Exception { Object[] parameters = { 3 }; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false, int.class); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); Class<?> clazz = createClass(TEST_CLASS_FQN, b); Constructor<?> constructor = clazz.getConstructor(new Class[] { int.class }); try { constructor.newInstance(parameters); } catch (Throwable t) { } verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, parameters); ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class); verify(hookDispatcher).dispatchConstructorAfterBody(eq(methodId), captor.capture(), eq(parameters)); assertThat(captor.getValue().getClass().getName(), is(TEST_CLASS_FQN)); verifyNoMoreInteractions(hookDispatcher); }
@Test public void staticConstructor() throws Exception { long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, true); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // create instance this.createInstance(TEST_CLASS_FQN, b); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, new Object[0]); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, null, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void constructorStringOneParameter() throws Exception { Object[] parameters = { "java.lang.String" }; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false, String.class); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); Class<?> clazz = createClass(TEST_CLASS_FQN, b); Constructor<?> constructor = clazz.getConstructor(new Class[] { String.class }); Object instance = constructor.newInstance(parameters); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, parameters); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, instance, parameters); verifyNoMoreInteractions(hookDispatcher); }
@Test public void constructorExceptionHandledResultReturned() throws Exception { Object[] parameters = { 11L }; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false, long.class); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); Class<?> clazz = createClass(TEST_CLASS_FQN, b); Constructor<?> constructor = clazz.getConstructor(new Class[] { long.class }); Object instance = constructor.newInstance(parameters); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, parameters); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, instance, parameters); verifyNoMoreInteractions(hookDispatcher); }
@Test public void constructorNullParameter() throws Exception { long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // create instance Object instance = this.createInstance(TEST_CLASS_FQN, b); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, new Object[0]); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, instance, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void exceptionThrowerIsInstrumented() throws Exception { String methodName = "throwsAndHandlesException"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationExceptionTestClass.class, methodName); doAnswer(METHOD_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(EXCEPTION_TEST_CLASS_FQN); prepareWriter(cr, null, true, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(EXCEPTION_TEST_CLASS_FQN, b); this.callMethod(testClass, methodName, null); verify(hookDispatcher).dispatchMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchFirstMethodAfterBody(methodId, testClass, new Object[0], null, false); verify(hookDispatcher).dispatchSecondMethodAfterBody(methodId, testClass, new Object[0], null, false); ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class); verify(hookDispatcher).dispatchBeforeCatch(eq(methodId), captor.capture()); assertThat(captor.getValue().getClass().getName(), is(equalTo(MyTestException.class.getName()))); verifyNoMoreInteractions(hookDispatcher); }
@Test public void doubleNullParameter() throws Exception { String methodName = "doubleNullParameter"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is((Object) Double.valueOf(5.3D))); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchSpecialMethodAfterBody(methodId, testClass, new Object[0], 5.3D); verifyNoMoreInteractions(hookDispatcher); }
@Test public void doubleNullParameterResultOnBefore() throws Exception { String methodName = "doubleNullParameter"; Double returnValue = Double.valueOf(45223.412D); long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); when(hookDispatcher.dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0])).thenReturn(returnValue); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is((Object) returnValue)); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void unexpectedExceptionTrowing() throws Exception { String methodName = "unexpectedExceptionThrowing"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); try { this.callMethod(testClass, methodName, null); } catch (Throwable t) { // NOPMD } ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchSpecialMethodAfterBody(eq(methodId), eq(testClass), eq(new Object[0]), captor.capture()); assertThat(captor.getValue(), is(instanceOf(Exception.class))); verifyNoMoreInteractions(hookDispatcher); }
@Test public void intNullParameterResultOnBefore() throws Exception { String methodName = "intNullParameter"; Object returnValue = Integer.valueOf(11); long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); when(hookDispatcher.dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0])).thenReturn(returnValue); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is(returnValue)); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void doubleNullParameterResultOnBeforeOtherPrimitive() throws Exception { String methodName = "doubleNullParameter"; Float returnValue = Float.valueOf(45223.412F); long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); when(hookDispatcher.dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0])).thenReturn(returnValue); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is((Object) Double.valueOf(5.3D))); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchSpecialMethodAfterBody(methodId, testClass, new Object[0], 5.3D); verifyNoMoreInteractions(hookDispatcher); }
@Test public void exceptionHandledResultReturned() throws Exception { String methodName = "exceptionHandledResultReturned"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is((Object) 3)); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchSpecialMethodAfterBody(methodId, testClass, new Object[0], 3); verifyNoMoreInteractions(hookDispatcher); }
@Test public void noParameters() throws Exception { String methodName = "intNullParameter"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(SPECIAL_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); when(hookDispatcher.dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0])).thenReturn(9); Object result = this.callMethod(testClass, methodName, null); assertThat(result, is((Object) Integer.valueOf(3))); verify(hookDispatcher).dispatchSpecialMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchSpecialMethodAfterBody(methodId, testClass, new Object[0], 3); verifyNoMoreInteractions(hookDispatcher); }