Repository: authorjapps/zerocode
Pull request #711 (2025-04-25 18:50:21)

Replace uniVocity CSV library with jackson-csv #702
# <Feature Title>

## Fixes Issue
- [https://github.com/authorjapps/zerocode/issues/702] Which issue or ticket was(will be) fixed by this PR? (capture the issue number)

PR Branch
**https://github.com/rkampani/zerocode/tree/feature/701-replaceUniVocityJar **

## Motivation and Context

## Checklist:

* [x] New Unit tests were added
  * [ ] Covered in existing Unit tests

* [ ] Integration tests were added
  * [ ] Covered in existing Integration tests

* [x] Test names are meaningful

* [ ] Feature manually tested and outcome is successful

* [x] PR doesn't break any of the earlier features for end users
  * [ ] WARNING! This might break one or more earlier earlier features, hence left a comment tagging all reviewrs

* [x] Branch build passed in CI

* [x] No 'package.*' in the imports

* [ ] Relevant DOcumentation page added or updated with clear instructions and examples for the end user
  * [ ] Not applicable. This was only a code refactor change, no functional or behaviourial changes were introduced

* [ ] Http test added to `http-testing` module(if applicable) ?
  * [ ] Not applicable. The changes did not affect HTTP automation flow

* [ ] Kafka test added to `kafka-testing` module(if applicable) ?
  * [ ] Not applicable. The changes did not affect Kafka automation flow



Patch:
diff --git a/core/pom.xml b/core/pom.xml
index 61377ed4..ce08281c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -62,10 +62,6 @@
             <groupId>com.fasterxml.jackson.dataformat</groupId>
             <artifactId>jackson-dataformat-yaml</artifactId>
         </dependency>
-        <dependency>
-            <groupId>com.univocity</groupId>
-            <artifactId>univocity-parsers</artifactId>
-        </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
diff --git a/core/src/main/java/org/jsmart/zerocode/core/db/DbCsvLoader.java b/core/src/main/java/org/jsmart/zerocode/core/db/DbCsvLoader.java
index 877f4469..ff8162d1 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/db/DbCsvLoader.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/db/DbCsvLoader.java
@@ -10,10 +10,10 @@ import java.util.stream.IntStream;
 
 import org.apache.commons.dbutils.QueryRunner;
 import org.apache.commons.lang3.StringUtils;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.univocity.parsers.csv.CsvParser;
 
 /**
  * Data loading in the database from a CSV external source
@@ -21,9 +21,9 @@ import com.univocity.parsers.csv.CsvParser;
 class DbCsvLoader {
 	private static final Logger LOGGER = LoggerFactory.getLogger(DbCsvLoader.class);
 	private Connection conn;
-	private CsvParser csvParser;
+	private CsvParserProvider csvParser;
 
-	public DbCsvLoader(Connection conn, CsvParser csvParser) {
+	public DbCsvLoader(Connection conn, CsvParserProvider csvParser) {
 		this.conn = conn;
 		this.csvParser = csvParser;
 	}
diff --git a/core/src/main/java/org/jsmart/zerocode/core/db/DbSqlExecutor.java b/core/src/main/java/org/jsmart/zerocode/core/db/DbSqlExecutor.java
index 22392d24..6c9b6c8f 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/db/DbSqlExecutor.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/db/DbSqlExecutor.java
@@ -3,9 +3,9 @@ package org.jsmart.zerocode.core.db;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
-import com.univocity.parsers.csv.CsvParser;
 
 import org.apache.commons.dbutils.DbUtils;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.sql.Connection;
@@ -36,7 +36,7 @@ public class DbSqlExecutor {
 	@Named("db.driver.password") private String password;
 	
     @Inject
-    private CsvParser csvParser;
+    private CsvParserProvider csvParser;
 	
 	/**
 	 * The LOADCSV operation inserts the content of a CSV file into a table,
diff --git a/core/src/main/java/org/jsmart/zerocode/core/di/module/CsvParserModule.java b/core/src/main/java/org/jsmart/zerocode/core/di/module/CsvParserModule.java
index bdb203b1..c0b13ac2 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/di/module/CsvParserModule.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/di/module/CsvParserModule.java
@@ -2,15 +2,15 @@ package org.jsmart.zerocode.core.di.module;
 
 import com.google.inject.Binder;
 import com.google.inject.Module;
-import com.univocity.parsers.csv.CsvParser;
 import jakarta.inject.Singleton;
+import org.jsmart.zerocode.core.di.provider.CsvParserInterface;
 import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 
 public class CsvParserModule implements Module {
 
     @Override
     public void configure(Binder binder) {
-        binder.bind(CsvParser.class).toProvider(CsvParserProvider.class).in(Singleton.class);
+        binder.bind(CsvParserInterface.class).toProvider(CsvParserProvider.class).in(Singleton.class);
     }
 }
 
diff --git a/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserConfig.java b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserConfig.java
new file mode 100644
index 00000000..4ca7c449
--- /dev/null
+++ b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserConfig.java
@@ -0,0 +1,72 @@
+package org.jsmart.zerocode.core.di.provider;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * /
+ *  Configuration class for parsing CSV files with Jackson's CSV module,
+ *  using a custom deserializer to maintain compatibility with non-standard formats previously handled by uniVocity.
+ *
+ */
+public class CsvParserConfig {
+
+    public static class CustomStringDeserializer extends StdDeserializer<String> {
+        // Immutable map of replacement rules: pattern → replacement
+        private static final Map<String, String> REPLACEMENTS = createReplacements();
+
+        /**
+         * Creates an immutable map of replacement rules for escape patterns.
+         * @return A map containing patterns and their replacements.
+         */
+        private static Map<String, String> createReplacements() {
+            Map<String, String> map = new HashMap<>();
+            map.put("\\'", "'"); // Backslash-escaped single quote
+            map.put("''", "'");  // Double single quote (single-quoted CSV)
+            map.put("\\\\", "\\"); // Double backslash to preserve literal backslash
+            return Collections.unmodifiableMap(map);
+        }
+
+        public CustomStringDeserializer() {
+            super(String.class);
+        }
+
+        /**
+         * Deserializes a String value from the CSV parser, applying custom escape pattern replacements.
+         * <p>
+         * The method processes the input string to handle non-standard escape patterns required
+         * for the expected output (e.g., <code>["a'c", "d\"f", "x\y"]</code>). It uses a stream-based
+         * approach to apply replacements only when the pattern is present, ensuring efficiency.
+         * <p>
+         * Without this deserializer, Jackson's default CSV parser may:
+         * <ul>
+         *     <li>Strip literal backslashes (e.g., <code>x\y</code> becomes <code>xy</code>).</li>
+         *     <li>Misinterpret single-quote escaping (e.g., <code>\'</code> or <code>''</code>).</li>
+         * </ul>
+         * <p>
+         * This implementation ensures compatibility with the previous CSV parsing library's behavior
+         * and handles inputs like <code>"a'c","d""f","x\y"</code> or <code>"a\'c","d\"f","x\y"</code>.
+         *
+         * @return The processed string with escape patterns replaced, or null if the input is null.
+         * @throws IOException If an I/O error occurs during parsing.
+         */
+        @Override
+        public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+            final String value = p.getText();
+            if (Objects.isNull(value)) {
+                return null;
+            }
+            return REPLACEMENTS.entrySet().stream()
+                    .filter(entry -> value.contains(entry.getKey()))
+                    .reduce(value, (current, entry) -> current.replace(entry.getKey(), entry.getValue()), (v1, v2) -> v1);
+        }
+    }
+
+}
diff --git a/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserInterface.java b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserInterface.java
new file mode 100644
index 00000000..0ea6c59f
--- /dev/null
+++ b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserInterface.java
@@ -0,0 +1,21 @@
+package org.jsmart.zerocode.core.di.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Defines a contract for parsing a single line of CSV data into a string array.
+ * Implementations should handle CSV lines with a specified format, such as
+ * comma-separated fields with optional quoting and escaping.
+ */
+public interface CsvParserInterface {
+    /**
+     * Parses a single line of CSV data into an array of fields.
+     *
+     * @param line the CSV line to parse, which may include quoted fields and escaped characters
+     * @return an array of strings representing the parsed fields; may be empty if the line is invalid
+     * @throws IOException if an error occurs during parsing, such as malformed CSV data
+     */
+    String[] parseLine(final String line) throws IOException;
+}
diff --git a/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserProvider.java b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserProvider.java
index c0148d64..32711361 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserProvider.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/di/provider/CsvParserProvider.java
@@ -1,27 +1,66 @@
 package org.jsmart.zerocode.core.di.provider;
 
-import com.univocity.parsers.csv.CsvParser;
-import com.univocity.parsers.csv.CsvParserSettings;
+
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvParser;
+import com.fasterxml.jackson.dataformat.csv.CsvSchema;
 import jakarta.inject.Provider;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
 
-public class CsvParserProvider implements Provider<CsvParser> {
+public class CsvParserProvider implements Provider<JacksonCsvParserAdapter> {
+    private static final Logger logger = LoggerFactory.getLogger(CsvParserProvider.class);
+    private static final JacksonCsvParserAdapter instance;
     public static final String LINE_SEPARATOR = "\n";
+    private static final String CARRIAGE_RETURN = "\r";
+
+    static {
+        final CsvSchema schema = createCsvSchema();
+        final CsvMapper csvMapper = new CsvMapper();
+        csvMapper.enable(CsvParser.Feature.TRIM_SPACES);
+        csvMapper.enable(CsvParser.Feature.ALLOW_TRAILING_COMMA);
+        csvMapper.registerModule(new SimpleModule()
+                .addDeserializer(String.class, new CsvParserConfig.CustomStringDeserializer()));
+        final ObjectReader mapper =  csvMapper
+                .enable(CsvParser.Feature.TRIM_SPACES)
+                .readerFor(String[].class)
+                .with(schema);
+        instance = new JacksonCsvParserAdapter(mapper);
+    }
 
     @Override
-    public CsvParser get() {
-        CsvParserSettings settings = createCsvSettings();
-        return new CsvParser(settings);
+    public JacksonCsvParserAdapter get() {
+        return instance;
+    }
+
+    public String[] parseLine(final String line) {
+        try {
+            return instance.parseLine(sanitizeLine(line));
+        } catch (final IOException e) {
+            logger.warn("Failed to parse line: {}", line, e);
+            return new String[0];
+        }
+    }
+
+    private String sanitizeLine(final String line) {
+        if (StringUtils.isNotBlank(line) && !line.contains(CARRIAGE_RETURN)) {
+            return line;
+        }
+        return line.replace(CARRIAGE_RETURN, StringUtils.SPACE);
     }
 
-    private CsvParserSettings createCsvSettings() {
-        CsvParserSettings settings = new CsvParserSettings();
-        settings.getFormat().setDelimiter(",");
-        settings.getFormat().setQuote('\'');
-        settings.getFormat().setQuoteEscape('\'');
-        settings.setEmptyValue("");
-        settings.getFormat().setLineSeparator("\n");
-        settings.setAutoConfigurationEnabled(false);
-        return settings;
+    private static CsvSchema createCsvSchema() {
+        return CsvSchema.builder()
+                .setColumnSeparator(',')
+                .setQuoteChar('\'')
+                .setNullValue("")
+                .setLineSeparator(LINE_SEPARATOR)
+                .build();
     }
 
 }
diff --git a/core/src/main/java/org/jsmart/zerocode/core/di/provider/JacksonCsvParserAdapter.java b/core/src/main/java/org/jsmart/zerocode/core/di/provider/JacksonCsvParserAdapter.java
new file mode 100644
index 00000000..efb47656
--- /dev/null
+++ b/core/src/main/java/org/jsmart/zerocode/core/di/provider/JacksonCsvParserAdapter.java
@@ -0,0 +1,23 @@
+package org.jsmart.zerocode.core.di.provider;
+
+import com.fasterxml.jackson.databind.ObjectReader;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+public class JacksonCsvParserAdapter implements CsvParserInterface {
+
+    private final ObjectReader mapper;
+    public JacksonCsvParserAdapter(final ObjectReader mapper) {
+        this.mapper = mapper;
+    }
+    @Override
+    public String[] parseLine(final String line) throws IOException {
+        if (StringUtils.isEmpty(line)) return null ;
+        if(line.trim().isEmpty()) {
+            return new String[]{ null };
+        }
+        return mapper.readValue(new StringReader(line));
+    }
+}
diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java
index 30ff1666..918c19cb 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java
@@ -3,9 +3,9 @@ package org.jsmart.zerocode.core.engine.preprocessor;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
-import com.univocity.parsers.csv.CsvParser;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.text.StringSubstitutor;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jsmart.zerocode.core.domain.ScenarioSpec;
 import org.jsmart.zerocode.core.utils.TokenUtils;
 import org.slf4j.Logger;
@@ -55,10 +55,10 @@ public class ZeroCodeParameterizedProcessorImpl implements ZeroCodeParameterized
 
     private final ObjectMapper objectMapper;
 
-    private final CsvParser csvParser;
+    private final CsvParserProvider csvParser;
 
     @Inject
-    public ZeroCodeParameterizedProcessorImpl(ObjectMapper objectMapper, CsvParser csvParser) {
+    public ZeroCodeParameterizedProcessorImpl(ObjectMapper objectMapper, CsvParserProvider csvParser) {
         this.objectMapper = objectMapper;
         this.csvParser = csvParser;
     }
diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
index ca551836..2169a739 100644
--- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
+++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java
@@ -6,11 +6,12 @@ import com.fasterxml.jackson.databind.node.NullNode;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
-import com.univocity.parsers.csv.CsvParser;
+
 import static java.util.Optional.ofNullable;
 import static org.apache.commons.collections4.CollectionUtils.isEmpty;
 import static org.jsmart.zerocode.core.constants.ZerocodeConstants.KAFKA_TOPIC;
 
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jsmart.zerocode.core.domain.Parameterized;
 import org.jsmart.zerocode.core.domain.ScenarioSpec;
 import org.jsmart.zerocode.core.domain.Step;
@@ -72,8 +73,7 @@ public class ZeroCodeMultiStepsScenarioRunnerImpl implements ZeroCodeMultiStepsS
     private ApiServiceExecutor apiExecutor;
 
     @Inject
-    private CsvParser csvParser;
-
+    private CsvParserProvider csvParser;
     @Inject
     private ApiTypeUtils apiTypeUtils;
 
diff --git a/pom.xml b/pom.xml
index 0e162aa9..277a9a61 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,7 +93,6 @@
         <extentreports.version>5.0.9</extentreports.version>
         <version.kafka-clients>3.7.0</version.kafka-clients>
         <version.gson>2.10.1</version.gson>
-        <version.univocity-parsers>2.8.2</version.univocity-parsers>
 
         <!-- Maven plugins, build properties  -->
         <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
@@ -310,11 +309,6 @@
                 <artifactId>extentreports</artifactId>
                 <version>${extentreports.version}</version> <!-- extent community version -->
             </dependency>
-            <dependency>
-                <groupId>com.univocity</groupId>
-                <artifactId>univocity-parsers</artifactId>
-                <version>${version.univocity-parsers}</version>
-            </dependency>
             <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
 			<dependency>
     			<groupId>com.google.protobuf</groupId>


Test patch:
diff --git a/core/src/test/java/org/jsmart/zerocode/core/db/DbCsvLoaderTest.java b/core/src/test/java/org/jsmart/zerocode/core/db/DbCsvLoaderTest.java
index 80729ad3..5916b846 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/db/DbCsvLoaderTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/db/DbCsvLoaderTest.java
@@ -9,12 +9,12 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jukito.JukitoRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import com.google.inject.Inject;
-import com.univocity.parsers.csv.CsvParser;
 
 @RunWith(JukitoRunner.class)
 public class DbCsvLoaderTest extends DbTestBase{
@@ -22,7 +22,7 @@ public class DbCsvLoaderTest extends DbTestBase{
 	private DbCsvLoader loader;
 	
 	@Inject
-	CsvParser csvParser;
+	CsvParserProvider csvParser;
 	
 	@Override
 	public void setUp() throws SQLException {
diff --git a/core/src/test/java/org/jsmart/zerocode/core/di/CsvParserTest.java b/core/src/test/java/org/jsmart/zerocode/core/di/CsvParserTest.java
new file mode 100644
index 00000000..47ea6a3a
--- /dev/null
+++ b/core/src/test/java/org/jsmart/zerocode/core/di/CsvParserTest.java
@@ -0,0 +1,64 @@
+package org.jsmart.zerocode.core.di;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNull;
+
+import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
+import org.jukito.JukitoRunner;
+import org.jukito.TestModule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.google.inject.Inject;
+
+
+@RunWith(JukitoRunner.class)
+public class CsvParserTest {
+
+    public static class JukitoModule extends TestModule {
+        @Override
+        protected void configureTest() {
+            ApplicationMainModule applicationMainModule = new ApplicationMainModule("config_hosts_test.properties");
+            install(applicationMainModule);
+        }
+    }
+
+    @Inject
+    CsvParserProvider parser;
+
+    @Test
+    public void testCsvparseSpaces() {
+        assertThat(parser.parseLine(" abc ,\t de f  , ghi "), is(new String[] { "abc", "de f", "ghi" }));
+    }
+
+    @Test
+    public void testCsvParseEmptyCell() {
+        assertThat(parser.parseLine(",,  , \t ,"), is(new String[] { null, null, null, null, null }));
+    }
+
+    @Test
+    public void testCsvparseEmptyLine() {
+        assertNull(parser.parseLine(""));
+        assertThat(parser.parseLine("  "), is(new String[] { null }));
+        assertThat(parser.parseLine(" \t "), is(new String[] { null }));
+    }
+
+    @Test
+    public void testCsvParseQuotesAndOtherChars() {
+        assertThat(parser.parseLine("a'c, d\"f, x\\y"), is(new String[] { "a'c", "d\"f", "x\\y" }));
+        assertThat(parser.parseLine("euro\u20AC, año, naïf"), is(new String[] { "euro\u20AC", "año", "naïf" }));
+    }
+
+    @Test
+    public void testCsvParseWindowsEndings() { // assume that lines where already splitted by \n
+        assertThat(parser.parseLine("abc, def\r"), is(new String[] { "abc", "def" }));
+        assertThat(parser.parseLine("abc, def \r"), is(new String[] { "abc", "def" }));
+        // empty lines
+        assertThat(parser.parseLine("\r"), is(new String[] { null })); // should be null?, see testCsvparseEmptyLine
+        assertThat(parser.parseLine("  \r"), is(new String[] { null }));
+        assertThat(parser.parseLine(" \t \r"), is(new String[] { null }));
+    }
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java
index 09569bd2..0728e28b 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java
@@ -2,8 +2,9 @@ package org.jsmart.zerocode.core.domain;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
-import com.univocity.parsers.csv.CsvParser;
+
 import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jsmart.zerocode.core.utils.SmartUtils;
 import org.jukito.JukitoRunner;
 import org.jukito.TestModule;
@@ -34,7 +35,7 @@ public class ParameterizedTest {
     private ObjectMapper mapper;
 
     @Inject
-    private CsvParser csvParser;
+    private CsvParserProvider csvParser;
 
     @Test
     public void testSerDe_valueSource() throws Exception {
diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
index 788a7ee6..16cb92c5 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/domain/StepTest.java
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Inject;
 import com.jayway.jsonpath.JsonPath;
-import com.univocity.parsers.csv.CsvParser;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -12,6 +11,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
 import org.jsmart.zerocode.core.utils.SmartUtils;
 import org.jukito.JukitoRunner;
@@ -50,7 +50,7 @@ public class StepTest {
     private ObjectMapper mapper;
 
     @Inject
-    private CsvParser csvParser;
+    private CsvParserProvider csvParser;
 
     @Test
     public void shouldDeserializeSingleStep() throws Exception {
diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImplTest.java
index 6f2e03a8..c135f3e7 100644
--- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImplTest.java
+++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImplTest.java
@@ -2,9 +2,9 @@ package org.jsmart.zerocode.core.engine.preprocessor;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.univocity.parsers.csv.CsvParser;
 import jakarta.inject.Inject;
 import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
+import org.jsmart.zerocode.core.di.provider.CsvParserProvider;
 import org.jsmart.zerocode.core.domain.ScenarioSpec;
 import org.jsmart.zerocode.core.domain.Step;
 import org.jsmart.zerocode.core.utils.SmartUtils;
@@ -40,7 +40,7 @@ public class ZeroCodeParameterizedProcessorImplTest {
     private ObjectMapper mapper;
 
     @Inject
-    private CsvParser csvParser;
+    private CsvParserProvider csvParser;
 
 
     private ZeroCodeParameterizedProcessorImpl parameterizedProcessor;