private void findAndSetFields() throws IllegalAccessException, NoSuchFieldException { Field[] fields = getClass().getDeclaredFields(); for (Field field : fields) { if (field.getAnnotation(InjectMocks.class) != null){ field.setAccessible(true); Object obj = field.get(this); if (MvpPresenter.class.isAssignableFrom(obj.getClass())){ findAndSetField(obj, "executorService", new RoboExecutorService()); findAndSetField(obj, "handler", new Handler(Looper.myLooper())); findAndSetField(obj, "eventBus", eventBus); } } } }
@Override protected void injectDependencies(TestContext testContext) throws Exception { super.injectDependencies(testContext); /** * 获取测试类 & fields */ Object bean = testContext.getTestInstance(); List<Field> fields = getDeclaredFields(bean); if (CollectionUtils.isEmpty(fields)) { return; } /** * 如果测试类中, 被测试对象含有mockito的@InjectMocks注解,且 被测试对象被事务拦截器拦截 则 用原始对象代替 */ for (Field field : fields) { InjectMocks injectMocks = field.getAnnotation(InjectMocks.class); if (injectMocks == null) { continue; } field.setAccessible(true); Object proxy = field.get(bean); if (AopUtils.isAopProxy(proxy)) { // 替换对象 Object target = ((Advised) proxy).getTargetSource().getTarget(); field.set(bean, target); } } }
@Override public void testFinished(Description description) throws Exception { try { Mockito.validateMockitoUsage(); if (!testClass.getAnnotatedFields(InjectMocks.class).isEmpty()) { throw new IllegalStateException("Do not use @InjectMocks with the DelayedInjectionRunner:" + " use @InjectDelayed or change runner"); } } catch (Exception e) { notifier.fireTestFailure(new Failure(description, e)); } }
private void resetMocks(Object instance) { Iterable<InstanceField> toReset = Fields.allDeclaredFieldsOf(instance) .filter(annotatedBy(Mock.class, InjectMocks.class, Spy.class)) .notNull() .instanceFields(); for (InstanceField field : toReset) { field.set(null); } }
@Test public void shouldReportNicely() throws Exception { Object failing = new Object() { @InjectMocks ThrowingConstructor c; }; try { MockitoAnnotations.initMocks(failing); fail(); } catch (MockitoException e) { assertContains("correct usage of @InjectMocks", e.getMessage()); } }
@Test(expected = MockitoException.class) public void shouldFailForLocalTypeField() throws Exception { // when class LocalType { }; class TheTestWithLocalType { @InjectMocks LocalType field; } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); }
public void shouldNotFailIfLocalTypeFieldIsInstantiated() throws Exception { // when class LocalType { }; class TheTestWithLocalType { @InjectMocks LocalType field = new LocalType(); } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); }
/** * Scan fields annotated by @InjectMocks * * @return Fields that depends on Mock */ private Set<Field> scan() { Set<Field> mockDependentFields = new HashSet<Field>(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (null != field.getAnnotation(InjectMocks.class)) { assertNoAnnotations(field, Mock.class, MockitoAnnotations.Mock.class, Captor.class); mockDependentFields.add(field); } } return mockDependentFields; }
void assertNoAnnotations(final Field field, final Class... annotations) { for (Class annotation : annotations) { if (field.isAnnotationPresent(annotation)) { new Reporter().unsupportedCombinationOfAnnotations(annotation.getSimpleName(), InjectMocks.class.getSimpleName()); } } }
@Test public void shouldReportNicely() throws Exception { Object failing = new Object() { @InjectMocks ThrowingConstructor failingConstructor; }; try { MockitoAnnotations.initMocks(failing); fail(); } catch (MockitoException e) { Assertions.assertThat(e.getMessage()).contains("failingConstructor").contains("constructor").contains("threw an exception"); Assertions.assertThat(e.getCause()).isInstanceOf(RuntimeException.class); } }
@Test(expected = MockitoException.class) public void should_fail_for_local_type_field() throws Exception { // when class LocalType { } class TheTestWithLocalType { @InjectMocks LocalType field; } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); }
@Test public void should_not_fail_if_local_type_field_is_instantiated() throws Exception { // when class LocalType { } class TheTestWithLocalType { @InjectMocks LocalType field = new LocalType(); } TheTestWithLocalType testWithLocalType = new TheTestWithLocalType(); // when new FieldInitializer(testWithLocalType, testWithLocalType.getClass().getDeclaredField("field")); }
@Override public void afterTestMethod(TestContext testContext) throws Exception { super.afterTestMethod(testContext); DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) testContext.getApplicationContext() .getAutowireCapableBeanFactory(); /** * 方法结束后记录被测试对象的bean名称 */ Object bean = testContext.getTestInstance(); List<Field> fields = getDeclaredFields(bean); for (Field field : fields) { InjectMocks injectMocks = field.getAnnotation(InjectMocks.class); if (injectMocks == null) { continue; } Object testedBean = null; String testedBeanName = null; /** * 被测试的对象如果通过spring自动注入,则记录 * 两种注入方式 Autowired * Resource */ if (field.getAnnotation(Autowired.class) != null) { Qualifier qualifier = field.getAnnotation(Qualifier.class); testedBean = qualifier == null ? beanFactory.getBean(field.getType()) : beanFactory.getBean(qualifier.value()); testedBeanName = qualifier == null ? beanFactory.getBeanNamesForType(field.getType())[0] : qualifier.value(); } else if (field.getAnnotation(Resource.class) != null) { Resource resource = field.getAnnotation(Resource.class); Class<?> type = resource.type(); String name = resource.name(); if (StringUtils.isNotEmpty(name)) { testedBean = beanFactory.getBean(name); testedBeanName = name; } else { testedBean = (type != Object.class) ? beanFactory.getBean(type) : beanFactory.getBean(field.getType()); testedBeanName = (type != Object.class) ? beanFactory.getBeanNamesForType(type)[0] : beanFactory.getBeanNamesForType(field.getType())[0]; } } if (testedBean != null) { testedObjects.put(testedBeanName, testedBean); } } }
public AnnotationResolver(TestClass testClass, Object target) { this(testClass, target, Inject.class, InjectMocks.class, Mock.class, Spy.class, InjectDelayed.class); }
@Test(expected=MockitoException.class) public void shouldNotAllowSpyAndInjectMock() throws Exception { MockitoAnnotations.initMocks(new Object() { @InjectMocks @Spy List mock; }); }
@Test(expected=MockitoException.class) public void shouldNotAllowMockAndInjectMock() throws Exception { MockitoAnnotations.initMocks(new Object() { @InjectMocks @Mock List mock; }); }
@Test(expected=MockitoException.class) public void shouldNotAllowCaptorAndInjectMock() throws Exception { MockitoAnnotations.initMocks(new Object() { @InjectMocks @Captor ArgumentCaptor captor; }); }
private static Collection<Field> getInjectMocksFields(final Class<?> clazz) { return getFieldsByAnnotation(clazz, InjectMocks.class); }