Reduce use of mocking and simplify some tests (#12283)

* remove use of mocks for ServiceMetricEvent
* simplify KafkaEmitterTests by moving to Mockito
* speed up KafkaEmitterTest by adjusting reporting frequency in tests
* remove unnecessary easymock and JUnitParams dependencies
This commit is contained in:
Xavier Léauté 2022-02-26 17:23:09 -08:00 committed by GitHub
parent a080fcdd7b
commit 4c61878f9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 47 additions and 163 deletions

View File

@ -120,11 +120,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>pl.pragmatists</groupId> <groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId> <artifactId>JUnitParams</artifactId>

View File

@ -27,10 +27,8 @@ import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.java.util.emitter.service.ServiceMetricEvent; import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
import org.apache.hadoop.metrics2.sink.timeline.TimelineMetric; import org.apache.hadoop.metrics2.sink.timeline.TimelineMetric;
import org.easymock.EasyMock;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -38,7 +36,6 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.HashMap;
@RunWith(JUnitParamsRunner.class) @RunWith(JUnitParamsRunner.class)
@ -47,24 +44,11 @@ public class WhiteListBasedDruidToTimelineEventConverterTest
private final String prefix = "druid"; private final String prefix = "druid";
private final WhiteListBasedDruidToTimelineEventConverter defaultWhiteListBasedDruidToTimelineEventConverter = private final WhiteListBasedDruidToTimelineEventConverter defaultWhiteListBasedDruidToTimelineEventConverter =
new WhiteListBasedDruidToTimelineEventConverter(prefix, "druid", null, new DefaultObjectMapper()); new WhiteListBasedDruidToTimelineEventConverter(prefix, "druid", null, new DefaultObjectMapper());
private ServiceMetricEvent event;
private final DateTime createdTime = DateTimes.nowUtc(); private final DateTime createdTime = DateTimes.nowUtc();
private final String hostname = "testHost:8080"; private final String hostname = "testHost:8080";
private final String serviceName = "historical"; private final String serviceName = "historical";
private final String defaultNamespace = prefix + "." + serviceName; private final String defaultNamespace = prefix + "." + serviceName;
@Before
public void setUp()
{
event = EasyMock.createMock(ServiceMetricEvent.class);
EasyMock.expect(event.getHost()).andReturn(hostname).anyTimes();
EasyMock.expect(event.getService()).andReturn(serviceName).anyTimes();
EasyMock.expect(event.getCreatedTime()).andReturn(createdTime).anyTimes();
EasyMock.expect(event.getUserDims()).andReturn(new HashMap<>()).anyTimes();
EasyMock.expect(event.getValue()).andReturn(10).anyTimes();
EasyMock.expect(event.getFeed()).andReturn("metrics").anyTimes();
}
@Test @Test
@Parameters( @Parameters(
{ {
@ -90,8 +74,12 @@ public class WhiteListBasedDruidToTimelineEventConverterTest
) )
public void testDefaultIsInWhiteList(String key, boolean expectedValue) public void testDefaultIsInWhiteList(String key, boolean expectedValue)
{ {
EasyMock.expect(event.getMetric()).andReturn(key).anyTimes(); ServiceMetricEvent event = ServiceMetricEvent
EasyMock.replay(event); .builder()
.setFeed("metrics")
.build(createdTime, key, 10)
.build(serviceName, hostname);
boolean isIn = defaultWhiteListBasedDruidToTimelineEventConverter.druidEventToTimelineMetric(event) != null; boolean isIn = defaultWhiteListBasedDruidToTimelineEventConverter.druidEventToTimelineMetric(event) != null;
Assert.assertEquals(expectedValue, isIn); Assert.assertEquals(expectedValue, isIn);
} }

View File

@ -107,11 +107,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.hamcrest</groupId> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId> <artifactId>hamcrest-core</artifactId>

View File

@ -73,11 +73,6 @@
<artifactId>easymock</artifactId> <artifactId>easymock</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>
<artifactId>druid-processing</artifactId> <artifactId>druid-processing</artifactId>

View File

@ -103,11 +103,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>pl.pragmatists</groupId> <groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId> <artifactId>JUnitParams</artifactId>

View File

@ -26,10 +26,8 @@ import org.apache.druid.annotations.UsedByJUnitParamsRunner;
import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.java.util.emitter.service.ServiceMetricEvent; import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
import org.easymock.EasyMock;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -37,7 +35,6 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.HashMap;
@RunWith(JUnitParamsRunner.class) @RunWith(JUnitParamsRunner.class)
@ -52,22 +49,10 @@ public class WhiteListBasedConverterTest
null, null,
new DefaultObjectMapper() new DefaultObjectMapper()
); );
private ServiceMetricEvent event; private final DateTime createdTime = DateTimes.nowUtc();
private DateTime createdTime = DateTimes.nowUtc(); private final String hostname = "testHost.yahoo.com:8080";
private String hostname = "testHost.yahoo.com:8080"; private final String serviceName = "historical";
private String serviceName = "historical"; private final String defaultNamespace = prefix + "." + serviceName + "." + GraphiteEmitter.sanitize(hostname);
private String defaultNamespace = prefix + "." + serviceName + "." + GraphiteEmitter.sanitize(hostname);
@Before
public void setUp()
{
event = EasyMock.createMock(ServiceMetricEvent.class);
EasyMock.expect(event.getHost()).andReturn(hostname).anyTimes();
EasyMock.expect(event.getService()).andReturn(serviceName).anyTimes();
EasyMock.expect(event.getCreatedTime()).andReturn(createdTime).anyTimes();
EasyMock.expect(event.getUserDims()).andReturn(new HashMap<>()).anyTimes();
EasyMock.expect(event.getValue()).andReturn(10).anyTimes();
}
@Test @Test
@Parameters( @Parameters(
@ -94,8 +79,11 @@ public class WhiteListBasedConverterTest
) )
public void testDefaultIsInWhiteList(String key, boolean expectedValue) public void testDefaultIsInWhiteList(String key, boolean expectedValue)
{ {
EasyMock.expect(event.getMetric()).andReturn(key).anyTimes(); ServiceMetricEvent event = ServiceMetricEvent
EasyMock.replay(event); .builder()
.build(createdTime, key, 10)
.build(serviceName, hostname);
boolean isIn = defaultWhiteListBasedConverter.druidEventToGraphite(event) != null; boolean isIn = defaultWhiteListBasedConverter.druidEventToGraphite(event) != null;
Assert.assertEquals(expectedValue, isIn); Assert.assertEquals(expectedValue, isIn);
} }

View File

@ -81,16 +81,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>nl.jqno.equalsverifier</groupId> <groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId> <artifactId>equalsverifier</artifactId>

View File

@ -88,13 +88,8 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.easymock</groupId> <groupId>org.mockito</groupId>
<artifactId>easymock</artifactId> <artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -50,6 +50,8 @@ public class KafkaEmitter implements Emitter
{ {
private static Logger log = new Logger(KafkaEmitter.class); private static Logger log = new Logger(KafkaEmitter.class);
private static final int DEFAULT_SEND_INTERVAL_SECONDS = 10;
private static final int DEFAULT_SEND_LOST_INTERVAL_MINUTES = 5;
private static final int DEFAULT_RETRIES = 3; private static final int DEFAULT_RETRIES = 3;
private final AtomicLong metricLost; private final AtomicLong metricLost;
private final AtomicLong alertLost; private final AtomicLong alertLost;
@ -64,6 +66,8 @@ public class KafkaEmitter implements Emitter
private final MemoryBoundLinkedBlockingQueue<String> requestQueue; private final MemoryBoundLinkedBlockingQueue<String> requestQueue;
private final ScheduledExecutorService scheduler; private final ScheduledExecutorService scheduler;
protected int sendInterval = DEFAULT_SEND_INTERVAL_SECONDS;
public KafkaEmitter(KafkaEmitterConfig config, ObjectMapper jsonMapper) public KafkaEmitter(KafkaEmitterConfig config, ObjectMapper jsonMapper)
{ {
this.config = config; this.config = config;
@ -116,16 +120,16 @@ public class KafkaEmitter implements Emitter
@Override @Override
public void start() public void start()
{ {
scheduler.schedule(this::sendMetricToKafka, 10, TimeUnit.SECONDS); scheduler.schedule(this::sendMetricToKafka, sendInterval, TimeUnit.SECONDS);
scheduler.schedule(this::sendAlertToKafka, 10, TimeUnit.SECONDS); scheduler.schedule(this::sendAlertToKafka, sendInterval, TimeUnit.SECONDS);
if (config.getRequestTopic() != null) { if (config.getRequestTopic() != null) {
scheduler.schedule(this::sendRequestToKafka, 10, TimeUnit.SECONDS); scheduler.schedule(this::sendRequestToKafka, sendInterval, TimeUnit.SECONDS);
} }
scheduler.scheduleWithFixedDelay(() -> { scheduler.scheduleWithFixedDelay(() -> {
log.info("Message lost counter: metricLost=[%d], alertLost=[%d], requestLost=[%d], invalidLost=[%d]", log.info("Message lost counter: metricLost=[%d], alertLost=[%d], requestLost=[%d], invalidLost=[%d]",
metricLost.get(), alertLost.get(), requestLost.get(), invalidLost.get() metricLost.get(), alertLost.get(), requestLost.get(), invalidLost.get()
); );
}, 5, 5, TimeUnit.MINUTES); }, DEFAULT_SEND_LOST_INTERVAL_MINUTES, DEFAULT_SEND_LOST_INTERVAL_MINUTES, TimeUnit.MINUTES);
log.info("Starting Kafka Emitter."); log.info("Starting Kafka Emitter.");
} }
@ -144,8 +148,7 @@ public class KafkaEmitter implements Emitter
sendToKafka(config.getRequestTopic(), requestQueue, setProducerCallback(requestLost)); sendToKafka(config.getRequestTopic(), requestQueue, setProducerCallback(requestLost));
} }
@VisibleForTesting private void sendToKafka(final String topic, MemoryBoundLinkedBlockingQueue<String> recordQueue, Callback callback)
protected void sendToKafka(final String topic, MemoryBoundLinkedBlockingQueue<String> recordQueue, Callback callback)
{ {
ObjectContainer<String> objectToSend; ObjectContainer<String> objectToSend;
try { try {

View File

@ -30,10 +30,8 @@ import org.apache.druid.server.QueryStats;
import org.apache.druid.server.RequestLogLine; import org.apache.druid.server.RequestLogLine;
import org.apache.druid.server.log.DefaultRequestLogEventBuilderFactory; import org.apache.druid.server.log.DefaultRequestLogEventBuilderFactory;
import org.apache.druid.server.log.RequestLogEvent; import org.apache.druid.server.log.RequestLogEvent;
import org.apache.kafka.clients.producer.Callback;
import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.Producer;
import org.easymock.EasyMock;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -42,6 +40,10 @@ import org.junit.runners.Parameterized;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class KafkaEmitterTest public class KafkaEmitterTest
{ {
@ -57,8 +59,8 @@ public class KafkaEmitterTest
}; };
} }
// there is 10 seconds wait in kafka emitter before it starts sending events to broker, so set a timeout for 15 seconds // there is 1 seconds wait in kafka emitter before it starts sending events to broker, set a timeout for 5 seconds
@Test(timeout = 15_000) @Test(timeout = 5_000)
public void testKafkaEmitter() throws InterruptedException public void testKafkaEmitter() throws InterruptedException
{ {
final List<ServiceMetricEvent> serviceMetricEvents = ImmutableList.of( final List<ServiceMetricEvent> serviceMetricEvents = ImmutableList.of(
@ -80,7 +82,7 @@ public class KafkaEmitterTest
final CountDownLatch countDownSentEvents = new CountDownLatch( final CountDownLatch countDownSentEvents = new CountDownLatch(
requestTopic == null ? totalEventsExcludingRequestLogEvents : totalEvents); requestTopic == null ? totalEventsExcludingRequestLogEvents : totalEvents);
final KafkaProducer<String, String> producer = EasyMock.createStrictMock(KafkaProducer.class); final KafkaProducer<String, String> producer = mock(KafkaProducer.class);
final KafkaEmitter kafkaEmitter = new KafkaEmitter( final KafkaEmitter kafkaEmitter = new KafkaEmitter(
new KafkaEmitterConfig("", "metrics", "alerts", requestTopic, "test-cluster", null), new KafkaEmitterConfig("", "metrics", "alerts", requestTopic, "test-cluster", null),
new ObjectMapper() new ObjectMapper()
@ -89,22 +91,17 @@ public class KafkaEmitterTest
@Override @Override
protected Producer<String, String> setKafkaProducer() protected Producer<String, String> setKafkaProducer()
{ {
// override send interval to 1 second
sendInterval = 1;
return producer; return producer;
} }
@Override
protected void sendToKafka(final String topic, MemoryBoundLinkedBlockingQueue<String> recordQueue,
Callback callback
)
{
countDownSentEvents.countDown();
super.sendToKafka(topic, recordQueue, callback);
}
}; };
EasyMock.expect(producer.send(EasyMock.anyObject(), EasyMock.anyObject())).andReturn(null) when(producer.send(any(), any())).then((invocation) -> {
.times(requestTopic == null ? totalEventsExcludingRequestLogEvents : totalEvents); countDownSentEvents.countDown();
EasyMock.replay(producer); return null;
});
kafkaEmitter.start(); kafkaEmitter.start();
for (Event event : serviceMetricEvents) { for (Event event : serviceMetricEvents) {
@ -122,18 +119,5 @@ public class KafkaEmitterTest
Assert.assertEquals(0, kafkaEmitter.getAlertLostCount()); Assert.assertEquals(0, kafkaEmitter.getAlertLostCount());
Assert.assertEquals(requestTopic == null ? requestLogEvents.size() : 0, kafkaEmitter.getRequestLostCount()); Assert.assertEquals(requestTopic == null ? requestLogEvents.size() : 0, kafkaEmitter.getRequestLostCount());
Assert.assertEquals(0, kafkaEmitter.getInvalidLostCount()); Assert.assertEquals(0, kafkaEmitter.getInvalidLostCount());
while (true) {
try {
EasyMock.verify(producer);
break;
}
catch (Throwable e) {
// although the latch may have count down, producer.send may not have been called yet in KafkaEmitter
// so wait for sometime before verifying the mock
Thread.sleep(100);
// just continue
}
}
} }
} }

View File

@ -87,11 +87,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>nl.jqno.equalsverifier</groupId> <groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId> <artifactId>equalsverifier</artifactId>
@ -120,4 +115,4 @@
</dependencies> </dependencies>
</project> </project>

View File

@ -146,11 +146,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -100,11 +100,6 @@
<artifactId>easymock</artifactId> <artifactId>easymock</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>
<artifactId>druid-server</artifactId> <artifactId>druid-server</artifactId>

View File

@ -88,11 +88,6 @@
<artifactId>easymock</artifactId> <artifactId>easymock</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>
<artifactId>druid-server</artifactId> <artifactId>druid-server</artifactId>

View File

@ -83,11 +83,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>
<artifactId>druid-core</artifactId> <artifactId>druid-core</artifactId>

View File

@ -350,11 +350,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -160,11 +160,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>
<artifactId>druid-server</artifactId> <artifactId>druid-server</artifactId>

View File

@ -136,11 +136,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>

View File

@ -131,11 +131,6 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>nl.jqno.equalsverifier</groupId> <groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId> <artifactId>equalsverifier</artifactId>
@ -144,6 +139,12 @@
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.druid</groupId> <groupId>org.apache.druid</groupId>

View File

@ -420,11 +420,6 @@
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.github.os72</groupId> <groupId>com.github.os72</groupId>
<artifactId>protobuf-dynamic</artifactId> <artifactId>protobuf-dynamic</artifactId>