Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JMockit does not work with newest versions of JaCoCo plugin #748

Open
pksilen opened this issue Jan 4, 2024 · 1 comment
Open

JMockit does not work with newest versions of JaCoCo plugin #748

pksilen opened this issue Jan 4, 2024 · 1 comment

Comments

@pksilen
Copy link

pksilen commented Jan 4, 2024

  • JDK: 17
  • JMockit Version number: 1.49

Some unit tests throw ArrayIndexOutOfBoundsException when using
newest version 0.8.11 of the JaCoCo plugin. An older version of JaCoCo plugin like 0.8.3 works ok.

The expection is thrown in a test case where I mock a singleton class. If I remove the mocking the test case works ok.

Mocking of the below class in a test case field using the @mocked annotation cause all test cases in the module to fail with
the ArrayIndexOutOfBoundsException :

package com.nokia.cni.exportica.batchwriter.common.metrics;

import com.nokia.cni.exportica.batchwriter.application.config.ApplicationConfig;
import com.nokia.cni.exportica.batchwriter.common.configproperties.ConfigProperties;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterDescriptions;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.counter.CounterNames;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeDescriptions;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.gauge.GaugeNames;
import com.nokia.cni.exportica.batchwriter.common.metrics.label.LabelKey;
import com.nokia.cni.exportica.batchwriter.common.metrics.label.LabelNames;
import com.nokia.cni.exportica.batchwriter.messagequeue.MessageQueueConfig;
import com.nokia.cni.exportica.batchwriter.output.file.writer.config.FileWriterConfig;
import io.prometheus.client.Counter;
import io.prometheus.client.Gauge;

import java.util.*;

@SuppressWarnings("UseOfConcreteClass")
public final class Metrics {
    private static Metrics instance;
    final Map<CounterKey, Counter> keyToCounter = new EnumMap<>(CounterKey.class);
    final Map<GaugeKey, Gauge> keyToGauge = new EnumMap<>(GaugeKey.class);
    private final double msgQueueMaxLength;
    private final String productName;
    private final String useCaseName;
    private final String podName;
    private final String outputType;

    public static void createInstance(final ConfigProperties configProperties) {
        if (instance == null) {
            instance = new Metrics(configProperties);
        }
    }

    public static Metrics getInstance() {
        return instance;
    }

    @SuppressWarnings("LawOfDemeter")
    private Metrics(final ConfigProperties configProperties) {
        final var namesConfig = new ApplicationConfig(configProperties).namesConfig;
        productName = namesConfig.productName;
        useCaseName = namesConfig.useCaseName;
        podName = namesConfig.podName;
        outputType = new FileWriterConfig(configProperties).destType;
        msgQueueMaxLength = new MessageQueueConfig(configProperties).maxLength;
        createCounters();
        createGauges();
    }

    public void incrementCounter(final CounterKey key, final long value, final String kafkaTopic) {
        final var counter = keyToCounter.get(key);
        counter.labels(getLabelValues(kafkaTopic)).inc(value);
    }

    public void updateMsgQueueGauges(final int msgQueueLength) {
        keyToGauge.get(GaugeKey.MESSAGE_QUEUE_LENGTH).labels(getLabelValues("")).set(msgQueueLength);
        keyToGauge.get(GaugeKey.MESSAGE_QUEUE_UTILIZATION).labels(getLabelValues("")).set(msgQueueLength / msgQueueMaxLength);
    }

    private void createCounters() {
        Arrays.stream(CounterKey.values()).forEach(counterKey -> keyToCounter.put(counterKey, createCounter(counterKey)));
    }

    private Counter createCounter(final CounterKey counterKey) {
        return Counter.build()
                .name(createProductNamespacedMetricName(CounterNames.get(counterKey)))
                .help(CounterDescriptions.get(counterKey))
                .labelNames(getLabelNames())
                .register();
    }

    private void createGauges() {
        Arrays.stream(GaugeKey.values()).forEach(gaugeKey -> keyToGauge.put(gaugeKey, createGauge(gaugeKey)));
    }

    private Gauge createGauge(final GaugeKey gaugeKey) {
        return Gauge.build()
                .name(createProductNamespacedMetricName(GaugeNames.get(gaugeKey)))
                .help(GaugeDescriptions.get(gaugeKey))
                .labelNames(getLabelNames())
                .register();
    }

    private String createProductNamespacedMetricName(final String metricName) {
        final var productNameInMetricName = productName.replace("-", "_");
        return productNameInMetricName + '_' + metricName;
    }

    private static String[] getLabelNames() {
        return Arrays.stream(LabelKey.values()).map(LabelNames::get).toArray(String[]::new);
    }

    private String[] getLabelValues(final String kafkaTopic) {
        return new String[]{useCaseName, podName, outputType, kafkaTopic};
    }
}
@shivanisky
Copy link

You might want to migrate to mockito, as I hit the same issue.

Have built on @tinder-dthomson 's great work with much help from @timtebeek and added automation for more statements and improved robustness, including Jmockit Expectations, JMockit Verifications (v 8.29.0) and Jmockit NonStrictExpectations (v 8.30.0) . It's now looking like it would cover the majority of cases and may be worth exploring for migration to mockito

https://docs.openrewrite.org/recipes/java/testing/jmockit/jmockittomockito

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants