You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by jf...@apache.org on 2014/07/29 20:25:20 UTC

git commit: AURORA-145:Test dependencies leak into distribution

Repository: incubator-aurora
Updated Branches:
  refs/heads/master db2173e04 -> 44a9501aa


AURORA-145:Test dependencies leak into distribution

Moves testing dependencies out of main src into test.

Testing Done:
Was initially waiting on AURORA-132 for this. ran build-support/jenkins/build.sh and created dists with no issues.

Bugs closed: AURORA-145

Reviewed at https://reviews.apache.org/r/19796/


Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/44a9501a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/44a9501a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/44a9501a

Branch: refs/heads/master
Commit: 44a9501aaf15ff1a462e30340eb205154d0e5e47
Parents: db2173e
Author: jfarrell <jf...@apache.org>
Authored: Tue Jul 29 14:10:25 2014 -0400
Committer: jfarrell <jf...@apache.org>
Committed: Tue Jul 29 14:13:54 2014 -0400

----------------------------------------------------------------------
 build.gradle                                    |   6 +-
 .../storage/log/testing/LogOpMatcher.java       | 112 ---------------
 .../storage/testing/StorageTestUtil.java        | 143 -------------------
 .../storage/log/testing/LogOpMatcher.java       | 112 +++++++++++++++
 .../storage/testing/StorageTestUtil.java        | 143 +++++++++++++++++++
 5 files changed, 258 insertions(+), 258 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/44a9501a/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 650338f..22ac386 100644
--- a/build.gradle
+++ b/build.gradle
@@ -204,16 +204,16 @@ dependencies {
   compile 'com.twitter.common:net-util:0.0.80'
   compile 'com.twitter.common:quantity:0.0.71'
   compile 'com.twitter.common:stats:0.0.91'
-  compile 'com.twitter.common:testing-easymock:0.0.4'
   compile 'com.twitter.common:thrift:0.0.68'
   compile 'com.twitter.common:util-executor-service-shutdown:0.0.49'
-  compile 'com.twitter.common:util-system-mocks:0.0.72'
   compile 'com.twitter.common:util-templating:0.0.25'
   compile 'com.twitter.common:util-testing:0.0.10'
   compile 'com.twitter.common:util:0.0.94'
-  compile 'com.twitter.common:zookeeper-testing:0.0.45'
 
   testCompile "com.sun.jersey:jersey-client:${jerseyRev}"
+  testCompile 'com.twitter.common:testing-easymock:0.0.4'
+  testCompile 'com.twitter.common:util-system-mocks:0.0.72'
+  testCompile 'com.twitter.common:zookeeper-testing:0.0.45'
   testCompile "junit:junit:${junitRev}"
 
   generatedCompile gsonDep

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/44a9501a/src/main/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java b/src/main/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
deleted file mode 100644
index 9abdbbb..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.log.testing;
-
-import java.util.Objects;
-
-import com.google.common.collect.ImmutableList;
-
-import org.apache.aurora.codec.ThriftBinaryCodec;
-import org.apache.aurora.codec.ThriftBinaryCodec.CodingException;
-import org.apache.aurora.gen.storage.LogEntry;
-import org.apache.aurora.gen.storage.Op;
-import org.apache.aurora.gen.storage.Snapshot;
-import org.apache.aurora.gen.storage.Transaction;
-import org.apache.aurora.gen.storage.storageConstants;
-import org.apache.aurora.scheduler.log.Log.Position;
-import org.apache.aurora.scheduler.log.Log.Stream;
-import org.easymock.EasyMock;
-import org.easymock.IArgumentMatcher;
-import org.easymock.IExpectationSetters;
-
-import static org.easymock.EasyMock.expect;
-
-/**
- * A junit argument matcher that detects same-value {@link LogEntry} objects in a more human
- * readable way than byte array comparison.
- */
-public class LogOpMatcher implements IArgumentMatcher {
-  private final LogEntry expected;
-
-  public LogOpMatcher(LogEntry expected) {
-    this.expected = expected;
-  }
-
-  @Override
-  public boolean matches(Object argument) {
-    try {
-      return expected.equals(ThriftBinaryCodec.decodeNonNull(LogEntry.class, (byte[]) argument));
-    } catch (CodingException e) {
-      return false;
-    }
-  }
-
-  @Override
-  public void appendTo(StringBuffer buffer) {
-    buffer.append(expected);
-  }
-
-  /**
-   * Creates a stream matcher that will set expectations on the provided {@code stream}.
-   *
-   * @param stream Mocked stream.
-   * @return A stream matcher to set expectations against {@code stream}.
-   */
-  public static StreamMatcher matcherFor(Stream stream) {
-    return new StreamMatcher(stream);
-  }
-
-  public static final class StreamMatcher {
-    private final Stream stream;
-
-    StreamMatcher(Stream stream) {
-      this.stream = Objects.requireNonNull(stream);
-    }
-
-    /**
-     * Sets an expectation for a stream transaction containing the provided {@code ops}.
-     *
-     * @param ops Operations to expect in the transaction.
-     * @return An expectation setter.
-     */
-    public IExpectationSetters<Position> expectTransaction(Op...ops) {
-      LogEntry entry = LogEntry.transaction(
-          new Transaction(ImmutableList.copyOf(ops), storageConstants.CURRENT_SCHEMA_VERSION));
-      return expect(stream.append(sameEntry(entry)));
-    }
-
-    /**
-     * Sets an expectation for a snapshot.
-     *
-     * @param snapshot Expected snapshot.
-     * @return An expectation setter.
-     */
-    public IExpectationSetters<Position> expectSnapshot(Snapshot snapshot) {
-      LogEntry entry = LogEntry.snapshot(snapshot);
-      return expect(stream.append(sameEntry(entry)));
-    }
-  }
-
-  /**
-   * Creates a matcher that supports value matching between a serialized {@link LogEntry} byte array
-   * and a log entry object.
-   *
-   * @param entry Entry to match against.
-   * @return {@code null}, return value included for easymock-style embedding.
-   */
-  private static byte[] sameEntry(LogEntry entry) {
-    EasyMock.reportMatcher(new LogOpMatcher(entry));
-    return new byte[] {};
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/44a9501a/src/main/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java b/src/main/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
deleted file mode 100644
index defafb6..0000000
--- a/src/main/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.scheduler.storage.testing;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import com.twitter.common.testing.easymock.EasyMockTest;
-
-import org.apache.aurora.scheduler.base.Query;
-import org.apache.aurora.scheduler.storage.AttributeStore;
-import org.apache.aurora.scheduler.storage.JobStore;
-import org.apache.aurora.scheduler.storage.LockStore;
-import org.apache.aurora.scheduler.storage.QuotaStore;
-import org.apache.aurora.scheduler.storage.SchedulerStore;
-import org.apache.aurora.scheduler.storage.Storage.MutableStoreProvider;
-import org.apache.aurora.scheduler.storage.Storage.MutateWork;
-import org.apache.aurora.scheduler.storage.Storage.NonVolatileStorage;
-import org.apache.aurora.scheduler.storage.Storage.StoreProvider;
-import org.apache.aurora.scheduler.storage.Storage.Work;
-import org.apache.aurora.scheduler.storage.TaskStore;
-import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
-import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
-import org.easymock.Capture;
-import org.easymock.IAnswer;
-import org.easymock.IExpectationSetters;
-
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.expect;
-
-/**
- * Auxiliary class to simplify testing against a mocked storage.  This allows callers to directly
- * set up call expectations on individual stores rather than writing plumbing code to deal with
- * operations and {@link StoreProvider}.
- */
-public class StorageTestUtil {
-
-  public final StoreProvider storeProvider;
-  public final MutableStoreProvider mutableStoreProvider;
-  public final TaskStore.Mutable taskStore;
-  public final QuotaStore.Mutable quotaStore;
-  public final AttributeStore.Mutable attributeStore;
-  public final JobStore.Mutable jobStore;
-  public final LockStore.Mutable lockStore;
-  public final SchedulerStore.Mutable schedulerStore;
-  public final NonVolatileStorage storage;
-
-  /**
-   * Creates a new storage test utility.
-   *
-   * @param easyMock Mocking framework to use for setting up mocks and expectations.
-   */
-  public StorageTestUtil(EasyMockTest easyMock) {
-    this.storeProvider = easyMock.createMock(StoreProvider.class);
-    this.mutableStoreProvider = easyMock.createMock(MutableStoreProvider.class);
-    this.taskStore = easyMock.createMock(TaskStore.Mutable.class);
-    this.quotaStore = easyMock.createMock(QuotaStore.Mutable.class);
-    this.attributeStore = easyMock.createMock(AttributeStore.Mutable.class);
-    this.jobStore = easyMock.createMock(JobStore.Mutable.class);
-    this.lockStore = easyMock.createMock(LockStore.Mutable.class);
-    this.schedulerStore = easyMock.createMock(SchedulerStore.Mutable.class);
-    this.storage = easyMock.createMock(NonVolatileStorage.class);
-  }
-
-  public <T> IExpectationSetters<T> expectConsistentRead() {
-    final Capture<Work<T, RuntimeException>> work = EasyMockTest.createCapture();
-    return expect(storage.<T, RuntimeException>consistentRead(capture(work)))
-        .andAnswer(new IAnswer<T>() {
-          @Override
-          public T answer() {
-            return work.getValue().apply(storeProvider);
-          }
-        });
-  }
-
-  public <T> IExpectationSetters<T> expectWeaklyConsistentRead() {
-    final Capture<Work<T, RuntimeException>> work = EasyMockTest.createCapture();
-    return expect(storage.<T, RuntimeException>weaklyConsistentRead(capture(work)))
-        .andAnswer(new IAnswer<T>() {
-          @Override
-          public T answer() {
-            return work.getValue().apply(storeProvider);
-          }
-        });
-  }
-
-  public <T> IExpectationSetters<T> expectWriteOperation() {
-    final Capture<MutateWork<T, RuntimeException>> work = EasyMockTest.createCapture();
-    return expect(storage.<T, RuntimeException>write(capture(work))).andAnswer(new IAnswer<T>() {
-      @Override
-      public T answer() {
-        return work.getValue().apply(mutableStoreProvider);
-      }
-    });
-  }
-
-  /**
-   * Expects any number of read or write operations.
-   */
-  public void expectOperations() {
-    expect(storeProvider.getTaskStore()).andReturn(taskStore).anyTimes();
-    expect(storeProvider.getQuotaStore()).andReturn(quotaStore).anyTimes();
-    expect(storeProvider.getAttributeStore()).andReturn(attributeStore).anyTimes();
-    expect(storeProvider.getJobStore()).andReturn(jobStore).anyTimes();
-    expect(storeProvider.getLockStore()).andReturn(lockStore).anyTimes();
-    expect(storeProvider.getSchedulerStore()).andReturn(schedulerStore).anyTimes();
-    expect(mutableStoreProvider.getTaskStore()).andReturn(taskStore).anyTimes();
-    expect(mutableStoreProvider.getUnsafeTaskStore()).andReturn(taskStore).anyTimes();
-    expect(mutableStoreProvider.getQuotaStore()).andReturn(quotaStore).anyTimes();
-    expect(mutableStoreProvider.getAttributeStore()).andReturn(attributeStore).anyTimes();
-    expect(mutableStoreProvider.getJobStore()).andReturn(jobStore).anyTimes();
-    expect(mutableStoreProvider.getLockStore()).andReturn(lockStore).anyTimes();
-    expect(mutableStoreProvider.getSchedulerStore()).andReturn(schedulerStore).anyTimes();
-    expectConsistentRead().anyTimes();
-    expectWeaklyConsistentRead().anyTimes();
-    expectWriteOperation().anyTimes();
-  }
-
-  public IExpectationSetters<?> expectTaskFetch(
-      Query.Builder query,
-      ImmutableSet<IScheduledTask> result) {
-
-    return expect(taskStore.fetchTasks(query)).andReturn(result);
-  }
-
-  public IExpectationSetters<?> expectTaskFetch(Query.Builder query, IScheduledTask... result) {
-    return expectTaskFetch(query, ImmutableSet.<IScheduledTask>builder().add(result).build());
-  }
-
-  public IExpectationSetters<?> expectQuotaFetch(String role, Optional<IResourceAggregate> result) {
-    return expect(quotaStore.fetchQuota(role)).andReturn(result);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/44a9501a/src/test/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java b/src/test/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
new file mode 100644
index 0000000..9abdbbb
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/storage/log/testing/LogOpMatcher.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.log.testing;
+
+import java.util.Objects;
+
+import com.google.common.collect.ImmutableList;
+
+import org.apache.aurora.codec.ThriftBinaryCodec;
+import org.apache.aurora.codec.ThriftBinaryCodec.CodingException;
+import org.apache.aurora.gen.storage.LogEntry;
+import org.apache.aurora.gen.storage.Op;
+import org.apache.aurora.gen.storage.Snapshot;
+import org.apache.aurora.gen.storage.Transaction;
+import org.apache.aurora.gen.storage.storageConstants;
+import org.apache.aurora.scheduler.log.Log.Position;
+import org.apache.aurora.scheduler.log.Log.Stream;
+import org.easymock.EasyMock;
+import org.easymock.IArgumentMatcher;
+import org.easymock.IExpectationSetters;
+
+import static org.easymock.EasyMock.expect;
+
+/**
+ * A junit argument matcher that detects same-value {@link LogEntry} objects in a more human
+ * readable way than byte array comparison.
+ */
+public class LogOpMatcher implements IArgumentMatcher {
+  private final LogEntry expected;
+
+  public LogOpMatcher(LogEntry expected) {
+    this.expected = expected;
+  }
+
+  @Override
+  public boolean matches(Object argument) {
+    try {
+      return expected.equals(ThriftBinaryCodec.decodeNonNull(LogEntry.class, (byte[]) argument));
+    } catch (CodingException e) {
+      return false;
+    }
+  }
+
+  @Override
+  public void appendTo(StringBuffer buffer) {
+    buffer.append(expected);
+  }
+
+  /**
+   * Creates a stream matcher that will set expectations on the provided {@code stream}.
+   *
+   * @param stream Mocked stream.
+   * @return A stream matcher to set expectations against {@code stream}.
+   */
+  public static StreamMatcher matcherFor(Stream stream) {
+    return new StreamMatcher(stream);
+  }
+
+  public static final class StreamMatcher {
+    private final Stream stream;
+
+    StreamMatcher(Stream stream) {
+      this.stream = Objects.requireNonNull(stream);
+    }
+
+    /**
+     * Sets an expectation for a stream transaction containing the provided {@code ops}.
+     *
+     * @param ops Operations to expect in the transaction.
+     * @return An expectation setter.
+     */
+    public IExpectationSetters<Position> expectTransaction(Op...ops) {
+      LogEntry entry = LogEntry.transaction(
+          new Transaction(ImmutableList.copyOf(ops), storageConstants.CURRENT_SCHEMA_VERSION));
+      return expect(stream.append(sameEntry(entry)));
+    }
+
+    /**
+     * Sets an expectation for a snapshot.
+     *
+     * @param snapshot Expected snapshot.
+     * @return An expectation setter.
+     */
+    public IExpectationSetters<Position> expectSnapshot(Snapshot snapshot) {
+      LogEntry entry = LogEntry.snapshot(snapshot);
+      return expect(stream.append(sameEntry(entry)));
+    }
+  }
+
+  /**
+   * Creates a matcher that supports value matching between a serialized {@link LogEntry} byte array
+   * and a log entry object.
+   *
+   * @param entry Entry to match against.
+   * @return {@code null}, return value included for easymock-style embedding.
+   */
+  private static byte[] sameEntry(LogEntry entry) {
+    EasyMock.reportMatcher(new LogOpMatcher(entry));
+    return new byte[] {};
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/44a9501a/src/test/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java b/src/test/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
new file mode 100644
index 0000000..defafb6
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/storage/testing/StorageTestUtil.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.aurora.scheduler.storage.testing;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.twitter.common.testing.easymock.EasyMockTest;
+
+import org.apache.aurora.scheduler.base.Query;
+import org.apache.aurora.scheduler.storage.AttributeStore;
+import org.apache.aurora.scheduler.storage.JobStore;
+import org.apache.aurora.scheduler.storage.LockStore;
+import org.apache.aurora.scheduler.storage.QuotaStore;
+import org.apache.aurora.scheduler.storage.SchedulerStore;
+import org.apache.aurora.scheduler.storage.Storage.MutableStoreProvider;
+import org.apache.aurora.scheduler.storage.Storage.MutateWork;
+import org.apache.aurora.scheduler.storage.Storage.NonVolatileStorage;
+import org.apache.aurora.scheduler.storage.Storage.StoreProvider;
+import org.apache.aurora.scheduler.storage.Storage.Work;
+import org.apache.aurora.scheduler.storage.TaskStore;
+import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
+import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
+import org.easymock.Capture;
+import org.easymock.IAnswer;
+import org.easymock.IExpectationSetters;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.expect;
+
+/**
+ * Auxiliary class to simplify testing against a mocked storage.  This allows callers to directly
+ * set up call expectations on individual stores rather than writing plumbing code to deal with
+ * operations and {@link StoreProvider}.
+ */
+public class StorageTestUtil {
+
+  public final StoreProvider storeProvider;
+  public final MutableStoreProvider mutableStoreProvider;
+  public final TaskStore.Mutable taskStore;
+  public final QuotaStore.Mutable quotaStore;
+  public final AttributeStore.Mutable attributeStore;
+  public final JobStore.Mutable jobStore;
+  public final LockStore.Mutable lockStore;
+  public final SchedulerStore.Mutable schedulerStore;
+  public final NonVolatileStorage storage;
+
+  /**
+   * Creates a new storage test utility.
+   *
+   * @param easyMock Mocking framework to use for setting up mocks and expectations.
+   */
+  public StorageTestUtil(EasyMockTest easyMock) {
+    this.storeProvider = easyMock.createMock(StoreProvider.class);
+    this.mutableStoreProvider = easyMock.createMock(MutableStoreProvider.class);
+    this.taskStore = easyMock.createMock(TaskStore.Mutable.class);
+    this.quotaStore = easyMock.createMock(QuotaStore.Mutable.class);
+    this.attributeStore = easyMock.createMock(AttributeStore.Mutable.class);
+    this.jobStore = easyMock.createMock(JobStore.Mutable.class);
+    this.lockStore = easyMock.createMock(LockStore.Mutable.class);
+    this.schedulerStore = easyMock.createMock(SchedulerStore.Mutable.class);
+    this.storage = easyMock.createMock(NonVolatileStorage.class);
+  }
+
+  public <T> IExpectationSetters<T> expectConsistentRead() {
+    final Capture<Work<T, RuntimeException>> work = EasyMockTest.createCapture();
+    return expect(storage.<T, RuntimeException>consistentRead(capture(work)))
+        .andAnswer(new IAnswer<T>() {
+          @Override
+          public T answer() {
+            return work.getValue().apply(storeProvider);
+          }
+        });
+  }
+
+  public <T> IExpectationSetters<T> expectWeaklyConsistentRead() {
+    final Capture<Work<T, RuntimeException>> work = EasyMockTest.createCapture();
+    return expect(storage.<T, RuntimeException>weaklyConsistentRead(capture(work)))
+        .andAnswer(new IAnswer<T>() {
+          @Override
+          public T answer() {
+            return work.getValue().apply(storeProvider);
+          }
+        });
+  }
+
+  public <T> IExpectationSetters<T> expectWriteOperation() {
+    final Capture<MutateWork<T, RuntimeException>> work = EasyMockTest.createCapture();
+    return expect(storage.<T, RuntimeException>write(capture(work))).andAnswer(new IAnswer<T>() {
+      @Override
+      public T answer() {
+        return work.getValue().apply(mutableStoreProvider);
+      }
+    });
+  }
+
+  /**
+   * Expects any number of read or write operations.
+   */
+  public void expectOperations() {
+    expect(storeProvider.getTaskStore()).andReturn(taskStore).anyTimes();
+    expect(storeProvider.getQuotaStore()).andReturn(quotaStore).anyTimes();
+    expect(storeProvider.getAttributeStore()).andReturn(attributeStore).anyTimes();
+    expect(storeProvider.getJobStore()).andReturn(jobStore).anyTimes();
+    expect(storeProvider.getLockStore()).andReturn(lockStore).anyTimes();
+    expect(storeProvider.getSchedulerStore()).andReturn(schedulerStore).anyTimes();
+    expect(mutableStoreProvider.getTaskStore()).andReturn(taskStore).anyTimes();
+    expect(mutableStoreProvider.getUnsafeTaskStore()).andReturn(taskStore).anyTimes();
+    expect(mutableStoreProvider.getQuotaStore()).andReturn(quotaStore).anyTimes();
+    expect(mutableStoreProvider.getAttributeStore()).andReturn(attributeStore).anyTimes();
+    expect(mutableStoreProvider.getJobStore()).andReturn(jobStore).anyTimes();
+    expect(mutableStoreProvider.getLockStore()).andReturn(lockStore).anyTimes();
+    expect(mutableStoreProvider.getSchedulerStore()).andReturn(schedulerStore).anyTimes();
+    expectConsistentRead().anyTimes();
+    expectWeaklyConsistentRead().anyTimes();
+    expectWriteOperation().anyTimes();
+  }
+
+  public IExpectationSetters<?> expectTaskFetch(
+      Query.Builder query,
+      ImmutableSet<IScheduledTask> result) {
+
+    return expect(taskStore.fetchTasks(query)).andReturn(result);
+  }
+
+  public IExpectationSetters<?> expectTaskFetch(Query.Builder query, IScheduledTask... result) {
+    return expectTaskFetch(query, ImmutableSet.<IScheduledTask>builder().add(result).build());
+  }
+
+  public IExpectationSetters<?> expectQuotaFetch(String role, Optional<IResourceAggregate> result) {
+    return expect(quotaStore.fetchQuota(role)).andReturn(result);
+  }
+}