/** * Verifies that an explicit task reconciliation for the task statuses in the provided persister was invoked. */ public static Expect reconciledExplicitly(Persister persisterWithStatuses) { // Use a custom comparator for sorting: Protos don't implement Comparable final Comparator<Protos.TaskStatus> statusComparator = new Comparator<Protos.TaskStatus>() { @Override public int compare(TaskStatus o1, TaskStatus o2) { return o1.getTaskId().getValue().compareTo(o2.getTaskId().getValue()); } }; return new Expect() { // Use this form instead of using ArgumentCaptor.forClass() to avoid problems with typecasting generics: @Captor private ArgumentCaptor<Collection<Protos.TaskStatus>> statusCaptor; @Override public void expect(ClusterState state, SchedulerDriver mockDriver) { MockitoAnnotations.initMocks(this); verify(mockDriver, atLeastOnce()).reconcileTasks(statusCaptor.capture()); Set<Protos.TaskStatus> expected = new TreeSet<>(statusComparator); expected.addAll(new StateStore(persisterWithStatuses).fetchStatuses()); Set<Protos.TaskStatus> got = new TreeSet<>(statusComparator); got.addAll(statusCaptor.getValue()); Assert.assertEquals(expected, got); } @Override public String getDescription() { return String.format("Explicit task reconcile call for statuses: %s", new StateStore(persisterWithStatuses).fetchStatuses().stream() .map(status -> String.format("%s=%s", status.getTaskId().getValue(), status.getState())) .collect(Collectors.toList())); } }; }
private void injectCaptor(Object testInstance) throws Exception { Set<Field> fieldsAnnotatedWithCaptor = Whitebox.getFieldsAnnotatedWith(testInstance, Captor.class); for (Field field : fieldsAnnotatedWithCaptor) { final Object captor = processAnnotationOn(field.getAnnotation(Captor.class),field); field.set(testInstance, captor); } }
private Object processAnnotationOn(Captor annotation, Field field) { Class<?> type = field.getType(); if (!ArgumentCaptor.class.isAssignableFrom(type)) { throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '" + field.getName() + "' has wrong type\n" + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class."); } Class cls = new GenericMaster().getGenericType(field); return ArgumentCaptor.forClass(cls); }
@Test public void test() { UUID dest = system.addActor(new ActorFactory() { @Override public Actor create() { return new Actor("UnhandledFeatureActor") { @Mock protected Appender mockAppender; @Captor protected ArgumentCaptor<LoggingEvent> captorLoggingEvent; @Override public void receive(ActorMessage<?> message) { MockitoAnnotations.initMocks(this); logger().removeAllAppenders(); logger().addAppender(mockAppender); unhandled(message); verify(mockAppender, times(1)).doAppend(captorLoggingEvent.capture()); LoggingEvent loggingEvent = captorLoggingEvent.getValue(); assertTrue(loggingEvent.getMessage().toString().contains("Unhandled message")); } }; } }); system.send(new ActorMessage<Object>(null, 0, system.SYSTEM_ID, dest)); system.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } system.shutdown(true); }
@SuppressWarnings("deprecation") public Object createMockFor(Annotation annotation, Field field) { if (annotation instanceof Mock) { return processAnnotationOn((Mock) annotation, field); } if (annotation instanceof MockitoAnnotations.Mock) { return processAnnotationOn((MockitoAnnotations.Mock) annotation, field); } if (annotation instanceof Captor) { return processAnnotationOn((Captor) annotation, field); } return null; }
/** * 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; }
public Object process(Captor annotation, Field field) { Class<?> type = field.getType(); if (!ArgumentCaptor.class.isAssignableFrom(type)) { throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '" + field.getName() + "' has wrong type\n" + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class."); } Class cls = new GenericMaster().getGenericType(field); return ArgumentCaptor.forClass(cls); }
/** * Verifies that a pod was launched with exactly the provided task names. */ public static Expect launchedTasks(Collection<String> taskNames) { return new Expect() { // Use this form instead of using ArgumentCaptor.forClass() to avoid problems with typecasting generics: @Captor private ArgumentCaptor<Collection<Protos.OfferID>> offerIdsCaptor; @Captor private ArgumentCaptor<Collection<Protos.Offer.Operation>> operationsCaptor; @Override public void expect(ClusterState state, SchedulerDriver mockDriver) { MockitoAnnotations.initMocks(this); verify(mockDriver, atLeastOnce()) .acceptOffers(offerIdsCaptor.capture(), operationsCaptor.capture(), any()); Protos.OfferID lastAcceptedOfferId = offerIdsCaptor.getValue().iterator().next(); Assert.assertEquals(String.format( "Expected last offer with ID %s to be accepted, but last accepted offer was %s", state.getLastOffer().getId().getValue(), lastAcceptedOfferId.getValue()), state.getLastOffer().getId(), lastAcceptedOfferId); Collection<String> launchedTaskNames = new ArrayList<>(); // A single acceptOffers() call may contain multiple LAUNCH/LAUNCH_GROUP operations. // We want to ensure they're all counted as a unit when tallying the pod. Collection<Protos.TaskInfo> launchedTaskInfos = new ArrayList<>(); for (Protos.Offer.Operation operation : operationsCaptor.getValue()) { if (operation.getType().equals(Protos.Offer.Operation.Type.LAUNCH)) { // Old-style launch with custom executor launchedTaskNames.addAll(operation.getLaunch().getTaskInfosList().stream() .map(task -> task.getName()) .collect(Collectors.toList())); launchedTaskInfos.addAll(operation.getLaunch().getTaskInfosList().stream() .map(task -> TaskPackingUtils.unpack(task)) .collect(Collectors.toList())); } else if (operation.getType().equals(Protos.Offer.Operation.Type.LAUNCH_GROUP)) { // New-style launch with default executor launchedTaskNames.addAll(operation.getLaunch().getTaskInfosList().stream() .map(task -> task.getName()) .collect(Collectors.toList())); launchedTaskInfos.addAll(operation.getLaunchGroup().getTaskGroup().getTasksList()); } } if (!launchedTaskInfos.isEmpty()) { state.addLaunchedPod(launchedTaskInfos); } Assert.assertTrue( String.format("Expected launched tasks: %s, got tasks: %s", taskNames, launchedTaskNames), launchedTaskNames.containsAll(taskNames) && taskNames.containsAll(launchedTaskNames)); } @Override public String getDescription() { return String.format("Tasks were launched into a pod: %s", taskNames); } }; }
/** * Verifies that the resources for the provided task names have been unreserved. */ public static Expect unreservedTasks(Collection<String> taskNames) { return new Expect() { // Use this form instead of using ArgumentCaptor.forClass() to avoid problems with typecasting generics: @Captor private ArgumentCaptor<Collection<Protos.OfferID>> offerIdsCaptor; @Captor private ArgumentCaptor<Collection<Protos.Offer.Operation>> operationsCaptor; @Override public void expect(ClusterState state, SchedulerDriver mockDriver) { MockitoAnnotations.initMocks(this); verify(mockDriver, atLeastOnce()) .acceptOffers(offerIdsCaptor.capture(), operationsCaptor.capture(), any()); Assert.assertEquals(state.getLastOffer().getId(), offerIdsCaptor.getValue().iterator().next()); Collection<String> expectedResourceIds = taskNames.stream() .map(taskName -> ResourceUtils.getResourceIds(state.getLastLaunchedTask(taskName).getResourcesList())) .flatMap(List::stream) .collect(Collectors.toList()); Assert.assertFalse(String.format("Expected some resource ids for tasks: %s, got none", taskNames), expectedResourceIds.isEmpty()); Collection<String> unreservedResourceIds = new ArrayList<>(); for (Protos.Offer.Operation operation : operationsCaptor.getValue()) { if (operation.getType().equals(Protos.Offer.Operation.Type.DESTROY)) { // Destroy volume(s) unreservedResourceIds.addAll( ResourceUtils.getResourceIds(operation.getDestroy().getVolumesList())); } else if (operation.getType().equals(Protos.Offer.Operation.Type.UNRESERVE)) { // Unreserve resource(s) unreservedResourceIds.addAll( ResourceUtils.getResourceIds(operation.getUnreserve().getResourcesList())); } } Assert.assertTrue( String.format("Expected unreserved resource ids: %s, got ids: %s", expectedResourceIds, unreservedResourceIds), unreservedResourceIds.containsAll(expectedResourceIds) && expectedResourceIds.containsAll(unreservedResourceIds)); } @Override public String getDescription() { return String.format("Resources for tasks have been unreserved: %s", taskNames); } }; }
private void initializeCaptors(Object instance) { List<InstanceField> instanceFields = Fields.allDeclaredFieldsOf(instance).filter(annotatedBy(Captor.class)).instanceFields(); for (InstanceField instanceField : instanceFields) { instanceField.set(new CaptorAnnotationProcessor().process(instanceField.annotation(Captor.class), instanceField.jdkField())); } }
@Test(expected=MockitoException.class) public void shouldNotAllowCaptorAndMock() throws Exception { MockitoAnnotations.initMocks(new Object() { @Mock @Captor ArgumentCaptor captor; }); }
@Test(expected=MockitoException.class) public void shouldNotAllowCaptorAndSpy() throws Exception { MockitoAnnotations.initMocks(new Object() { @Spy @Captor ArgumentCaptor captor; }); }
@Test(expected=MockitoException.class) public void shouldNotAllowCaptorAndInjectMock() throws Exception { MockitoAnnotations.initMocks(new Object() { @InjectMocks @Captor ArgumentCaptor captor; }); }
public DefaultAnnotationEngine() { registerAnnotationProcessor(Mock.class, new MockAnnotationProcessor()); registerAnnotationProcessor(MockitoAnnotations.Mock.class, new MockitoAnnotationsMockAnnotationProcessor()); registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor()); }