Reputation: 388
I want to write a unit test for a Scala class. The purpose of the class is to collect metrics and post them on a Kafka topic. I am trying to mock the producer in the unit test to ensure sanity of the rest of the code. Below is a simplified version of my class:
class MyEmitter(sparkConf: SparkConf) {
<snip> -- member variables
private val kafkaProducer = createProducer()
def createProducer(): Producer[String, MyMetricClass] = {
val props = new Properties()
...
Code to initialize properties
...
new KafkaProducer[String, MyMetricClass](props)
}
def initEmitter(metricName: String): SomeClass = {
// Some implementation
}
def collect(key: String, value: String): Unit = {
// Some implementation
}
def emit(): Unit = {
val record = new ProducerRecord("<topic name>", "<key>", "<value>")
kafkaProducer.send(record)
}
What I would like to do in my unit test is to mock out the producer and check whether the send() command has been called and, if so, whether the producer record matches the expectation. I have been unsuccessful to find a solution on my own. Googling the solution has also been unfruitful. If anyone knows how the problem could be solved, I will be most grateful.
Upvotes: 5
Views: 2305
Reputation: 1497
'new' is generally an enemy of testing, so you should extract the creation of that object so you can either pass a real KafkaProducer or a mock
One way to do it without changing the interface could be
def createProducer(
producer: Properties => KafkaProducer = props => new KafkaProducer[String, MyMetricClass](props)
): Producer[String, MyMetricClass] = {
val props = new Properties()
producer(props)
}
So then in real code you keep calling
myEmmiter.createProducer()
But in test you'd do
val producerMock = mock[KafkaProducer]
myEmmiter.createProducer(_ => producerMock)
Another good thing about this is that you could also stub the function itself so you can verify that the props
your method creates are the expected ones
Hope it helps
Upvotes: 4