Skip to content

Commit cc9eec1

Browse files
JoshRosenAndrew Or
authored and
Andrew Or
committed
[SPARK-5735] Replace uses of EasyMock with Mockito
This patch replaces all uses of EasyMock with Mockito. There are two motivations for this: 1. We should use a single mocking framework in our tests in order to keep things consistent. 2. EasyMock may be responsible for non-deterministic unit test failures due to its Objensis dependency (see SPARK-5626 for more details). Most of these changes are fairly mechanical translations of Mockito code to EasyMock, although I made a small change that strengthens the assertions in one test in KinesisReceiverSuite. Author: Josh Rosen <joshrosen@databricks.com> Closes #4578 from JoshRosen/SPARK-5735-remove-easymock and squashes the following commits: 0ab192b [Josh Rosen] Import sorting plus two minor changes to more closely match old semantics. 977565b [Josh Rosen] Remove EasyMock from build. fae1d8f [Josh Rosen] Remove EasyMock usage in KinesisReceiverSuite. 7cca486 [Josh Rosen] Remove EasyMock usage in MesosSchedulerBackendSuite fc5e94d [Josh Rosen] Remove EasyMock in CacheManagerSuite (cherry picked from commit 077eec2) Signed-off-by: Andrew Or <andrew@databricks.com>
1 parent e5690a5 commit cc9eec1

File tree

6 files changed

+207
-251
lines changed

6 files changed

+207
-251
lines changed

core/pom.xml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,6 @@
329329
<artifactId>scalacheck_${scala.binary.version}</artifactId>
330330
<scope>test</scope>
331331
</dependency>
332-
<dependency>
333-
<groupId>org.easymock</groupId>
334-
<artifactId>easymockclassextension</artifactId>
335-
<scope>test</scope>
336-
</dependency>
337-
<dependency>
338-
<groupId>asm</groupId>
339-
<artifactId>asm</artifactId>
340-
<scope>test</scope>
341-
</dependency>
342332
<dependency>
343333
<groupId>junit</groupId>
344334
<artifactId>junit</artifactId>

core/src/test/scala/org/apache/spark/CacheManagerSuite.scala

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717

1818
package org.apache.spark
1919

20+
import org.mockito.Mockito._
2021
import org.scalatest.{BeforeAndAfter, FunSuite}
21-
import org.scalatest.mock.EasyMockSugar
22+
import org.scalatest.mock.MockitoSugar
2223

23-
import org.apache.spark.executor.{DataReadMethod, TaskMetrics}
24+
import org.apache.spark.executor.DataReadMethod
2425
import org.apache.spark.rdd.RDD
2526
import org.apache.spark.storage._
2627

2728
// TODO: Test the CacheManager's thread-safety aspects
28-
class CacheManagerSuite extends FunSuite with BeforeAndAfter with EasyMockSugar {
29-
var sc : SparkContext = _
29+
class CacheManagerSuite extends FunSuite with LocalSparkContext with BeforeAndAfter
30+
with MockitoSugar {
31+
3032
var blockManager: BlockManager = _
3133
var cacheManager: CacheManager = _
3234
var split: Partition = _
@@ -57,10 +59,6 @@ class CacheManagerSuite extends FunSuite with BeforeAndAfter with EasyMockSugar
5759
}.cache()
5860
}
5961

60-
after {
61-
sc.stop()
62-
}
63-
6462
test("get uncached rdd") {
6563
// Do not mock this test, because attempting to match Array[Any], which is not covariant,
6664
// in blockManager.put is a losing battle. You have been warned.
@@ -75,29 +73,21 @@ class CacheManagerSuite extends FunSuite with BeforeAndAfter with EasyMockSugar
7573
}
7674

7775
test("get cached rdd") {
78-
expecting {
79-
val result = new BlockResult(Array(5, 6, 7).iterator, DataReadMethod.Memory, 12)
80-
blockManager.get(RDDBlockId(0, 0)).andReturn(Some(result))
81-
}
76+
val result = new BlockResult(Array(5, 6, 7).iterator, DataReadMethod.Memory, 12)
77+
when(blockManager.get(RDDBlockId(0, 0))).thenReturn(Some(result))
8278

83-
whenExecuting(blockManager) {
84-
val context = new TaskContextImpl(0, 0, 0, 0)
85-
val value = cacheManager.getOrCompute(rdd, split, context, StorageLevel.MEMORY_ONLY)
86-
assert(value.toList === List(5, 6, 7))
87-
}
79+
val context = new TaskContextImpl(0, 0, 0, 0)
80+
val value = cacheManager.getOrCompute(rdd, split, context, StorageLevel.MEMORY_ONLY)
81+
assert(value.toList === List(5, 6, 7))
8882
}
8983

9084
test("get uncached local rdd") {
91-
expecting {
92-
// Local computation should not persist the resulting value, so don't expect a put().
93-
blockManager.get(RDDBlockId(0, 0)).andReturn(None)
94-
}
85+
// Local computation should not persist the resulting value, so don't expect a put().
86+
when(blockManager.get(RDDBlockId(0, 0))).thenReturn(None)
9587

96-
whenExecuting(blockManager) {
97-
val context = new TaskContextImpl(0, 0, 0, 0, true)
98-
val value = cacheManager.getOrCompute(rdd, split, context, StorageLevel.MEMORY_ONLY)
99-
assert(value.toList === List(1, 2, 3, 4))
100-
}
88+
val context = new TaskContextImpl(0, 0, 0, 0, true)
89+
val value = cacheManager.getOrCompute(rdd, split, context, StorageLevel.MEMORY_ONLY)
90+
assert(value.toList === List(1, 2, 3, 4))
10191
}
10292

10393
test("verify task metrics updated correctly") {

core/src/test/scala/org/apache/spark/scheduler/mesos/MesosSchedulerBackendSuite.scala

Lines changed: 64 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,47 @@
1717

1818
package org.apache.spark.scheduler.mesos
1919

20-
import org.apache.spark.executor.MesosExecutorBackend
21-
import org.scalatest.FunSuite
22-
import org.apache.spark.{SparkConf, SparkContext, LocalSparkContext}
23-
import org.apache.spark.scheduler.{SparkListenerExecutorAdded, LiveListenerBus,
24-
TaskDescription, WorkerOffer, TaskSchedulerImpl}
25-
import org.apache.spark.scheduler.cluster.ExecutorInfo
26-
import org.apache.spark.scheduler.cluster.mesos.{MemoryUtils, MesosSchedulerBackend}
27-
import org.apache.mesos.SchedulerDriver
28-
import org.apache.mesos.Protos.{ExecutorInfo => MesosExecutorInfo, _}
29-
import org.apache.mesos.Protos.Value.Scalar
30-
import org.easymock.{Capture, EasyMock}
3120
import java.nio.ByteBuffer
32-
import java.util.Collections
3321
import java.util
34-
import org.scalatest.mock.EasyMockSugar
22+
import java.util.Collections
3523

3624
import scala.collection.mutable
3725
import scala.collection.mutable.ArrayBuffer
3826

39-
class MesosSchedulerBackendSuite extends FunSuite with LocalSparkContext with EasyMockSugar {
27+
import org.apache.mesos.SchedulerDriver
28+
import org.apache.mesos.Protos._
29+
import org.apache.mesos.Protos.Value.Scalar
30+
import org.mockito.Mockito._
31+
import org.mockito.Matchers._
32+
import org.mockito.{ArgumentCaptor, Matchers}
33+
import org.scalatest.FunSuite
34+
import org.scalatest.mock.MockitoSugar
35+
36+
import org.apache.spark.{LocalSparkContext, SparkConf, SparkContext}
37+
import org.apache.spark.executor.MesosExecutorBackend
38+
import org.apache.spark.scheduler._
39+
import org.apache.spark.scheduler.cluster.ExecutorInfo
40+
import org.apache.spark.scheduler.cluster.mesos.{MesosSchedulerBackend, MemoryUtils}
41+
42+
class MesosSchedulerBackendSuite extends FunSuite with LocalSparkContext with MockitoSugar {
4043

4144
test("check spark-class location correctly") {
4245
val conf = new SparkConf
4346
conf.set("spark.mesos.executor.home" , "/mesos-home")
4447

45-
val listenerBus = EasyMock.createMock(classOf[LiveListenerBus])
46-
listenerBus.post(SparkListenerExecutorAdded(EasyMock.anyLong, "s1", new ExecutorInfo("host1", 2, Map.empty)))
47-
EasyMock.replay(listenerBus)
48-
49-
val sc = EasyMock.createMock(classOf[SparkContext])
50-
EasyMock.expect(sc.getSparkHome()).andReturn(Option("/spark-home")).anyTimes()
51-
EasyMock.expect(sc.conf).andReturn(conf).anyTimes()
52-
EasyMock.expect(sc.executorEnvs).andReturn(new mutable.HashMap).anyTimes()
53-
EasyMock.expect(sc.executorMemory).andReturn(100).anyTimes()
54-
EasyMock.expect(sc.listenerBus).andReturn(listenerBus)
55-
EasyMock.replay(sc)
56-
val taskScheduler = EasyMock.createMock(classOf[TaskSchedulerImpl])
57-
EasyMock.expect(taskScheduler.CPUS_PER_TASK).andReturn(2).anyTimes()
58-
EasyMock.replay(taskScheduler)
48+
val listenerBus = mock[LiveListenerBus]
49+
listenerBus.post(
50+
SparkListenerExecutorAdded(anyLong, "s1", new ExecutorInfo("host1", 2, Map.empty)))
51+
52+
val sc = mock[SparkContext]
53+
when(sc.getSparkHome()).thenReturn(Option("/spark-home"))
54+
55+
when(sc.conf).thenReturn(conf)
56+
when(sc.executorEnvs).thenReturn(new mutable.HashMap[String, String])
57+
when(sc.executorMemory).thenReturn(100)
58+
when(sc.listenerBus).thenReturn(listenerBus)
59+
val taskScheduler = mock[TaskSchedulerImpl]
60+
when(taskScheduler.CPUS_PER_TASK).thenReturn(2)
5961

6062
val mesosSchedulerBackend = new MesosSchedulerBackend(taskScheduler, sc, "master")
6163

@@ -84,20 +86,19 @@ class MesosSchedulerBackendSuite extends FunSuite with LocalSparkContext with Ea
8486
.setSlaveId(SlaveID.newBuilder().setValue(s"s${id.toString}")).setHostname(s"host${id.toString}").build()
8587
}
8688

87-
val driver = EasyMock.createMock(classOf[SchedulerDriver])
88-
val taskScheduler = EasyMock.createMock(classOf[TaskSchedulerImpl])
89+
val driver = mock[SchedulerDriver]
90+
val taskScheduler = mock[TaskSchedulerImpl]
8991

90-
val listenerBus = EasyMock.createMock(classOf[LiveListenerBus])
91-
listenerBus.post(SparkListenerExecutorAdded(EasyMock.anyLong, "s1", new ExecutorInfo("host1", 2, Map.empty)))
92-
EasyMock.replay(listenerBus)
92+
val listenerBus = mock[LiveListenerBus]
93+
listenerBus.post(
94+
SparkListenerExecutorAdded(anyLong, "s1", new ExecutorInfo("host1", 2, Map.empty)))
9395

94-
val sc = EasyMock.createMock(classOf[SparkContext])
95-
EasyMock.expect(sc.executorMemory).andReturn(100).anyTimes()
96-
EasyMock.expect(sc.getSparkHome()).andReturn(Option("/path")).anyTimes()
97-
EasyMock.expect(sc.executorEnvs).andReturn(new mutable.HashMap).anyTimes()
98-
EasyMock.expect(sc.conf).andReturn(new SparkConf).anyTimes()
99-
EasyMock.expect(sc.listenerBus).andReturn(listenerBus)
100-
EasyMock.replay(sc)
96+
val sc = mock[SparkContext]
97+
when(sc.executorMemory).thenReturn(100)
98+
when(sc.getSparkHome()).thenReturn(Option("/path"))
99+
when(sc.executorEnvs).thenReturn(new mutable.HashMap[String, String])
100+
when(sc.conf).thenReturn(new SparkConf)
101+
when(sc.listenerBus).thenReturn(listenerBus)
101102

102103
val minMem = MemoryUtils.calculateTotalMemory(sc).toInt
103104
val minCpu = 4
@@ -121,25 +122,29 @@ class MesosSchedulerBackendSuite extends FunSuite with LocalSparkContext with Ea
121122
2
122123
))
123124
val taskDesc = new TaskDescription(1L, 0, "s1", "n1", 0, ByteBuffer.wrap(new Array[Byte](0)))
124-
EasyMock.expect(taskScheduler.resourceOffers(EasyMock.eq(expectedWorkerOffers))).andReturn(Seq(Seq(taskDesc)))
125-
EasyMock.expect(taskScheduler.CPUS_PER_TASK).andReturn(2).anyTimes()
126-
EasyMock.replay(taskScheduler)
125+
when(taskScheduler.resourceOffers(expectedWorkerOffers)).thenReturn(Seq(Seq(taskDesc)))
126+
when(taskScheduler.CPUS_PER_TASK).thenReturn(2)
127127

128-
val capture = new Capture[util.Collection[TaskInfo]]
129-
EasyMock.expect(
128+
val capture = ArgumentCaptor.forClass(classOf[util.Collection[TaskInfo]])
129+
when(
130130
driver.launchTasks(
131-
EasyMock.eq(Collections.singleton(mesosOffers.get(0).getId)),
132-
EasyMock.capture(capture),
133-
EasyMock.anyObject(classOf[Filters])
131+
Matchers.eq(Collections.singleton(mesosOffers.get(0).getId)),
132+
capture.capture(),
133+
any(classOf[Filters])
134134
)
135-
).andReturn(Status.valueOf(1)).once
136-
EasyMock.expect(driver.declineOffer(mesosOffers.get(1).getId)).andReturn(Status.valueOf(1)).times(1)
137-
EasyMock.expect(driver.declineOffer(mesosOffers.get(2).getId)).andReturn(Status.valueOf(1)).times(1)
138-
EasyMock.replay(driver)
135+
).thenReturn(Status.valueOf(1))
136+
when(driver.declineOffer(mesosOffers.get(1).getId)).thenReturn(Status.valueOf(1))
137+
when(driver.declineOffer(mesosOffers.get(2).getId)).thenReturn(Status.valueOf(1))
139138

140139
backend.resourceOffers(driver, mesosOffers)
141140

142-
EasyMock.verify(driver)
141+
verify(driver, times(1)).launchTasks(
142+
Matchers.eq(Collections.singleton(mesosOffers.get(0).getId)),
143+
capture.capture(),
144+
any(classOf[Filters])
145+
)
146+
verify(driver, times(1)).declineOffer(mesosOffers.get(1).getId)
147+
verify(driver, times(1)).declineOffer(mesosOffers.get(2).getId)
143148
assert(capture.getValue.size() == 1)
144149
val taskInfo = capture.getValue.iterator().next()
145150
assert(taskInfo.getName.equals("n1"))
@@ -151,15 +156,13 @@ class MesosSchedulerBackendSuite extends FunSuite with LocalSparkContext with Ea
151156
// Unwanted resources offered on an existing node. Make sure they are declined
152157
val mesosOffers2 = new java.util.ArrayList[Offer]
153158
mesosOffers2.add(createOffer(1, minMem, minCpu))
154-
EasyMock.reset(taskScheduler)
155-
EasyMock.reset(driver)
156-
EasyMock.expect(taskScheduler.resourceOffers(EasyMock.anyObject(classOf[Seq[WorkerOffer]])).andReturn(Seq(Seq())))
157-
EasyMock.expect(taskScheduler.CPUS_PER_TASK).andReturn(2).anyTimes()
158-
EasyMock.replay(taskScheduler)
159-
EasyMock.expect(driver.declineOffer(mesosOffers2.get(0).getId)).andReturn(Status.valueOf(1)).times(1)
160-
EasyMock.replay(driver)
159+
reset(taskScheduler)
160+
reset(driver)
161+
when(taskScheduler.resourceOffers(any(classOf[Seq[WorkerOffer]]))).thenReturn(Seq(Seq()))
162+
when(taskScheduler.CPUS_PER_TASK).thenReturn(2)
163+
when(driver.declineOffer(mesosOffers2.get(0).getId)).thenReturn(Status.valueOf(1))
161164

162165
backend.resourceOffers(driver, mesosOffers2)
163-
EasyMock.verify(driver)
166+
verify(driver, times(1)).declineOffer(mesosOffers2.get(0).getId)
164167
}
165168
}

extras/kinesis-asl/pom.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@
6767
<artifactId>scalacheck_${scala.binary.version}</artifactId>
6868
<scope>test</scope>
6969
</dependency>
70-
<dependency>
71-
<groupId>org.easymock</groupId>
72-
<artifactId>easymockclassextension</artifactId>
73-
<scope>test</scope>
74-
</dependency>
7570
<dependency>
7671
<groupId>com.novocode</groupId>
7772
<artifactId>junit-interface</artifactId>

0 commit comments

Comments
 (0)