View Javadoc
1   package com.opencsv.bean;
2   
3   import com.opencsv.*;
4   import com.opencsv.bean.mocks.*;
5   import com.opencsv.bean.verifier.PositiveEvensOnly;
6   import com.opencsv.bean.verifier.PositiveOddsOnly;
7   import com.opencsv.enums.CSVReaderNullFieldIndicator;
8   import com.opencsv.exceptions.CsvConstraintViolationException;
9   import com.opencsv.exceptions.CsvException;
10  import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
11  import org.apache.commons.lang3.StringUtils;
12  import org.junit.jupiter.api.*;
13  
14  import java.io.FileNotFoundException;
15  import java.io.FileReader;
16  import java.io.Reader;
17  import java.io.StringReader;
18  import java.util.List;
19  import java.util.Locale;
20  import java.util.stream.Collectors;
21  
22  import static org.junit.jupiter.api.Assertions.*;
23  
24  public class CsvToBeanTest {
25      private static final String TEST_STRING = "name,orderNumber,num\n" +
26              "kyle,abc123456,123\n" +
27              "jimmy,def098765,456 ";
28  
29      private static final String TEST_STRING_WITH_BLANK_LINES = "name,orderNumber,num\n" +
30              "kyle,abc123456,123\n\n\n" +
31              "jimmy,def098765,456";
32  
33      private static final String TEST_STRING_WITHOUT_MANDATORY_FIELD = "name,orderNumber,num\n" +
34              "kyle,abc123456,123\n" +
35              "jimmy,def098765,";
36  
37      private static final String GOOD_NUMBERS = "number\n0\n1\n2\n3\n4\n";
38      private static final String BAD_NUMBERS = "number\n0\n1\n2\n-5\n3\n4\n";
39  
40      private static Locale systemLocale;
41  
42      @BeforeAll
43      public static void storeSystemLocale() {
44          systemLocale = Locale.getDefault();
45      }
46  
47      @BeforeEach
48      public void setSystemLocaleToValueNotGerman() {
49          Locale.setDefault(Locale.US);
50      }
51  
52      @AfterEach
53      public void setSystemLocaleBackToDefault() {
54          Locale.setDefault(systemLocale);
55      }
56  
57      @SuppressWarnings("unchecked")
58      @Test
59      public void throwRuntimeExceptionWhenExceptionIsThrown() {
60          Assertions.assertThrows(RuntimeException.class, () -> {
61              new CsvToBeanBuilder(new StringReader(TEST_STRING))
62                      .withMappingStrategy(new ErrorHeaderMappingStrategy())
63                      .build().parse();
64          });
65      }
66  
67      @SuppressWarnings("unchecked")
68      @Test
69      public void throwRuntimeExceptionLineWhenExceptionIsThrown() {
70          Assertions.assertThrows(RuntimeException.class, () -> {
71              new CsvToBeanBuilder(new StringReader(TEST_STRING))
72                      .withMappingStrategy(new ErrorLineMappingStrategy())
73                      .withThrowExceptions(false)
74                      .build().parse(); // Extra arguments for code coverage
75          });
76      }
77  
78      @Test
79      public void parseBeanWithNoAnnotations() {
80          HeaderColumnNameMappingStrategy<MockBean> strategy = new HeaderColumnNameMappingStrategy<>();
81          strategy.setType(MockBean.class);
82          List<MockBean> beanList = new CsvToBeanBuilder<MockBean>(new StringReader(TEST_STRING))
83                  .withMappingStrategy(strategy)
84                  .withFilter(null)
85                  .build().parse(); // Extra arguments for code coverage
86  
87          assertEquals(2, beanList.size());
88          assertTrue(beanList.contains(new MockBean("kyle", null, "abc123456", 123, 0.0)));
89          assertTrue(beanList.contains(new MockBean("jimmy", null, "def098765", 456, 0.0)));
90      }
91  
92      @DisplayName("Blank lines are ignored when withIgnoreEmptyLine is set to true.")
93      @Test
94      public void parseBeanWithIgnoreEmptyLines() {
95          HeaderColumnNameMappingStrategy<MockBean> strategy = new HeaderColumnNameMappingStrategy<>();
96          strategy.setType(MockBean.class);
97          List<MockBean> beanList = new CsvToBeanBuilder<MockBean>(new StringReader(TEST_STRING_WITH_BLANK_LINES))
98                  .withMappingStrategy(strategy)
99                  .withIgnoreEmptyLine(true)
100                 .withFilter(null)
101                 .build().parse(); // Extra arguments for code coverage
102 
103         assertEquals(2, beanList.size());
104         assertTrue(beanList.contains(new MockBean("kyle", null, "abc123456", 123, 0.0)));
105         assertTrue(beanList.contains(new MockBean("jimmy", null, "def098765", 456, 0.0)));
106     }
107 
108     @DisplayName("Blank lines are ignored when withIgnoreEmptyLine is set to true and withFieldAsNull is set to EMPTY_SEPARATORS.")
109     @Test
110     public void parseBeanWithIgnoreEmptyLinesAndEmptyIsNull() {
111         HeaderColumnNameMappingStrategy<MockBean> strategy = new HeaderColumnNameMappingStrategy<>();
112         strategy.setType(MockBean.class);
113         List<MockBean> beanList = new CsvToBeanBuilder<MockBean>(new StringReader(TEST_STRING_WITH_BLANK_LINES))
114                 .withMappingStrategy(strategy)
115                 .withIgnoreEmptyLine(true)
116                 .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
117                 .build().parse();
118 
119         assertEquals(2, beanList.size());
120         assertTrue(beanList.contains(new MockBean("kyle", null, "abc123456", 123, 0.0)));
121         assertTrue(beanList.contains(new MockBean("jimmy", null, "def098765", 456, 0.0)));
122     }
123 
124     @Test
125     public void bug133ShouldNotThrowNullPointerExceptionWhenProcessingEmptyWithNoAnnotations() {
126         HeaderColumnNameMappingStrategy<Bug133Bean> strategy = new HeaderColumnNameMappingStrategy<>();
127         strategy.setType(Bug133Bean.class);
128 
129         StringReader reader = new StringReader("one;two;three\n" +
130                 "kyle;;123\n" +
131                 "jimmy;;456 ");
132 
133         CSVParserBuilder parserBuilder = new CSVParserBuilder();
134         CSVReaderBuilder readerBuilder = new CSVReaderBuilder(reader);
135 
136         CSVParser parser = parserBuilder.withFieldAsNull(CSVReaderNullFieldIndicator.BOTH).withSeparator(';').build();
137         CSVReader csvReader = readerBuilder.withCSVParser(parser).build();
138 
139         List<Bug133Bean> beanList = new CsvToBeanBuilder<Bug133Bean>(csvReader)
140                 .withMappingStrategy(strategy)
141                 .withFilter(null)
142                 .withThrowExceptions(true)
143                 .build().parse(); // Extra arguments for code coverage
144 
145         assertEquals(2, beanList.size());
146     }
147 
148     @Test
149     public void throwIllegalStateWhenParseWithoutArgumentsIsCalled() {
150         CsvToBean csvtb = new CsvToBean();
151         String englishErrorMessage = null;
152         try {
153             csvtb.parse();
154             fail("IllegalStateException should have been thrown.");
155         } catch (IllegalStateException e) {
156             englishErrorMessage = e.getLocalizedMessage();
157         }
158 
159         // Now with another locale
160         csvtb.setErrorLocale(Locale.GERMAN);
161         try {
162             csvtb.parse();
163             fail("IllegalStateException should have been thrown.");
164         } catch (IllegalStateException e) {
165             assertNotSame(englishErrorMessage, e.getLocalizedMessage());
166         }
167     }
168 
169     @Test
170     public void throwIllegalStateWhenOnlyReaderIsSpecifiedToParseWithoutArguments() {
171         CsvToBean csvtb = new CsvToBean();
172         csvtb.setCsvReader(new CSVReader(new StringReader(TEST_STRING)));
173         Assertions.assertThrows(IllegalStateException.class, csvtb::parse);
174     }
175 
176     @Test
177     public void throwIllegalStateWhenOnlyMapperIsSpecifiedToParseWithoutArguments() {
178         CsvToBean<AnnotatedMockBeanFull> csvtb = new CsvToBean<>();
179         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> strat = new HeaderColumnNameMappingStrategy<>();
180         strat.setType(AnnotatedMockBeanFull.class);
181         csvtb.setMappingStrategy(strat);
182         Assertions.assertThrows(IllegalStateException.class, csvtb::parse);
183     }
184 
185     @Test
186     public void throwIllegalArguementWhenReaderNotProvidedInBuilder() {
187         Assertions.assertThrows(IllegalArgumentException.class, () -> {
188             new CsvToBeanBuilder<AnnotatedMockBeanFull>((Reader) null)
189                     .withType(AnnotatedMockBeanFull.class)
190                     .build();
191         });
192     }
193 
194     @Test
195     public void throwIllegalStateWhenTypeAndMapperNotProvidedInBuilder() {
196         String englishErrorMessage = null;
197         try {
198             new CsvToBeanBuilder<>(new StringReader(TEST_STRING_WITHOUT_MANDATORY_FIELD))
199                     .build();
200             fail("IllegalStateException should have been thrown.");
201         } catch (IllegalStateException e) {
202             englishErrorMessage = e.getLocalizedMessage();
203         }
204 
205         // Now with a different locale
206         try {
207             new CsvToBeanBuilder<>(new StringReader(TEST_STRING_WITHOUT_MANDATORY_FIELD))
208                     .withErrorLocale(Locale.GERMAN)
209                     .build();
210             fail("IllegalStateException should have been thrown.");
211         } catch (IllegalStateException e) {
212             assertNotSame(englishErrorMessage, e.getLocalizedMessage());
213         }
214     }
215 
216     @Test
217     public void testMinimumBuilder() {
218         List<MinimalCsvBindByPositionBeanForWriting> result =
219                 new CsvToBeanBuilder<MinimalCsvBindByPositionBeanForWriting>(new StringReader("1,2,3\n4,5,6"))
220                         .withType(MinimalCsvBindByPositionBeanForWriting.class)
221                         .build()
222                         .parse();
223         assertEquals(2, result.size());
224     }
225 
226     @Test
227     public void testMinimumBuilderWithCSVReader() {
228         CSVReaderBuilder readerBuilder = new CSVReaderBuilder(new StringReader("1,2,3\n4,5,6"));
229         List<MinimalCsvBindByPositionBeanForWriting> result =
230                 new CsvToBeanBuilder<MinimalCsvBindByPositionBeanForWriting>(readerBuilder.build())
231                         .withType(MinimalCsvBindByPositionBeanForWriting.class)
232                         .build()
233                         .parse();
234         assertEquals(2, result.size());
235     }
236 
237     @Test
238     public void testParseVsStream() {
239         List<MinimalCsvBindByPositionBeanForWriting> resultList =
240                 new CsvToBeanBuilder<MinimalCsvBindByPositionBeanForWriting>(new StringReader("1,2,3\n4,5,6"))
241                         .withType(MinimalCsvBindByPositionBeanForWriting.class)
242                         .build()
243                         .parse();
244         List<MinimalCsvBindByPositionBeanForWriting> resultStream =
245                 new CsvToBeanBuilder<MinimalCsvBindByPositionBeanForWriting>(new StringReader("1,2,3\n4,5,6"))
246                         .withType(MinimalCsvBindByPositionBeanForWriting.class)
247                         .build()
248                         .stream().collect(Collectors.toList());
249         assertEquals(resultList, resultStream);
250     }
251 
252     private static class BegToBeFiltered implements CsvToBeanFilter {
253 
254         @Override
255         public boolean allowLine(String[] line) {
256             for (String col : line) {
257                 if (col.equals("filtermebaby")) return false;
258             }
259             return true;
260         }
261 
262     }
263 
264     @Test
265     public void testMaximumBuilder() throws FileNotFoundException {
266         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> map = new HeaderColumnNameMappingStrategy<>();
267         map.setType(AnnotatedMockBeanFull.class);
268 
269         // Yeah, some of these are the default values, but I'm having trouble concocting
270         // a CSV file screwy enough to meet the requirements posed by not using
271         // defaults for everything.
272         CsvToBean<AnnotatedMockBeanFull> csvtb =
273                 new CsvToBeanBuilder<AnnotatedMockBeanFull>(new FileReader("src/test/resources/testinputmaximumbuilder.csv"))
274                         .withEscapeChar('?')
275                         .withFieldAsNull(CSVReaderNullFieldIndicator.NEITHER) //default
276                         .withFilter(new BegToBeFiltered())
277                         .withIgnoreLeadingWhiteSpace(false)
278                         .withIgnoreQuotations(true)
279                         .withKeepCarriageReturn(false) //default
280                         .withMappingStrategy(map)
281                         .withQuoteChar('!')
282                         .withSeparator('#')
283                         .withSkipLines(1)
284                         .withStrictQuotes(false) // default
285                         .withThrowExceptions(false)
286                         .withType(AnnotatedMockBeanFull.class)
287                         .withVerifyReader(false)
288                         .withMultilineLimit(Integer.MAX_VALUE)
289                         .build();
290         List<CsvException> capturedExceptions = csvtb.getCapturedExceptions();
291         assertNotNull(capturedExceptions);
292         assertEquals(0, capturedExceptions.size());
293         List<AnnotatedMockBeanFull> result = csvtb.parse();
294 
295         // Three lines, one filtered, one throws an exception
296         assertEquals(1, result.size());
297         assertEquals(1, csvtb.getCapturedExceptions().size());
298         AnnotatedMockBeanFull bean = result.get(0);
299         assertEquals("\ttest string of everything!", bean.getStringClass());
300         assertTrue(bean.getBoolWrapped());
301         assertFalse(bean.isBoolPrimitive());
302         assertEquals(1, (byte) bean.getByteWrappedDefaultLocale());
303         // Nothing else really matters
304     }
305 
306     @Test
307     public void testMaximumBuilderWithCSVReader() throws FileNotFoundException {
308         HeaderColumnNameMappingStrategy<AnnotatedMockBeanFull> map = new HeaderColumnNameMappingStrategy<>();
309         map.setType(AnnotatedMockBeanFull.class);
310 
311         CSVParserBuilder cpb = new CSVParserBuilder();
312         CSVParser csvParser = cpb.withEscapeChar('?')
313                 .withFieldAsNull(CSVReaderNullFieldIndicator.NEITHER)
314                 .withIgnoreLeadingWhiteSpace(false)
315                 .withIgnoreQuotations(true)
316                 .withQuoteChar('!')
317                 .withSeparator('#')
318                 .withStrictQuotes(false)
319                 .build();
320 
321         CSVReaderBuilder crb = new CSVReaderBuilder(new FileReader("src/test/resources/testinputmaximumbuilder.csv"));
322         CSVReader csvReader = crb.withCSVParser(csvParser)
323                 .withSkipLines(1)
324                 .withKeepCarriageReturn(false)
325                 .withVerifyReader(false)
326                 .withMultilineLimit(Integer.MAX_VALUE)
327                 .build();
328 
329         // Yeah, some of these are the default values, but I'm having trouble concocting
330         // a CSV file screwy enough to meet the requirements posed by not using
331         // defaults for everything.
332         CsvToBean<AnnotatedMockBeanFull> csvtb =
333                 new CsvToBeanBuilder<AnnotatedMockBeanFull>(csvReader)
334                         .withFilter(new BegToBeFiltered())
335                         .withMappingStrategy(map)
336                         .withThrowExceptions(false)
337                         .withType(AnnotatedMockBeanFull.class)
338                         .build();
339         List<CsvException> capturedExceptions = csvtb.getCapturedExceptions();
340         assertNotNull(capturedExceptions);
341         assertEquals(0, capturedExceptions.size());
342         List<AnnotatedMockBeanFull> result = csvtb.parse();
343 
344         // Three lines, one filtered, one throws an exception
345         assertEquals(1, result.size());
346         assertEquals(1, csvtb.getCapturedExceptions().size());
347         AnnotatedMockBeanFull bean = result.get(0);
348         assertEquals("\ttest string of everything!", bean.getStringClass());
349         assertTrue(bean.getBoolWrapped());
350         assertFalse(bean.isBoolPrimitive());
351         assertEquals(1, (byte) bean.getByteWrappedDefaultLocale());
352         // Nothing else really matters
353     }
354 
355     @Test
356     public void testColumnMappingStrategyWithBuilder() throws FileNotFoundException {
357         List<AnnotatedMockBeanFull> result =
358                 new CsvToBeanBuilder<AnnotatedMockBeanFull>(new FileReader("src/test/resources/testinputposfullgood.csv"))
359                         .withSeparator(';')
360                         .withType(AnnotatedMockBeanFull.class)
361                         .build()
362                         .parse();
363         assertEquals(2, result.size());
364     }
365 
366     @Test
367     public void testMappingWithoutAnnotationsWithBuilder() {
368         List<MockBean> result =
369                 new CsvToBeanBuilder<MockBean>(new StringReader(TEST_STRING))
370                         .withType(MockBean.class)
371                         .build()
372                         .parse();
373         assertEquals(2, result.size());
374     }
375 
376     @Test
377     public void testEmptyInputWithHeaderNameMappingAndRequiredField() {
378         MappingStrategy<AnnotatedMockBeanFull> map = new HeaderColumnNameMappingStrategy<>();
379         map.setType(AnnotatedMockBeanFull.class);
380         try {
381             new CsvToBeanBuilder<AnnotatedMockBeanFull>(new StringReader(StringUtils.EMPTY))
382                     .withType(AnnotatedMockBeanFull.class)
383                     .withMappingStrategy(map)
384                     .build()
385                     .parse();
386             fail("An exception should have been thrown.");
387         } catch (RuntimeException re) {
388             Throwable t = re.getCause();
389             assertNotNull(t);
390             assertTrue(t instanceof CsvRequiredFieldEmptyException);
391         }
392     }
393 
394     @Test
395     public void testMismatchNumberOfData() {
396         MappingStrategy<AnnotatedMockBeanFull> map = new HeaderColumnNameMappingStrategy<>();
397         map.setType(AnnotatedMockBeanFull.class);
398         StringBuilder sb = new StringBuilder(ICSVParser.INITIAL_READ_SIZE);
399         String dateString = "19780115T063209";
400         sb.append("BYTE1,BYTE2,BYTE3,DATE1\n");
401         sb.append("1,2,3,").append(dateString).append("\n");
402         sb.append("4,5,6,").append(dateString).append("\n");
403         sb.append("7\n");
404         sb.append("8,9,10,").append(dateString).append("\n");
405         try {
406             new CsvToBeanBuilder<AnnotatedMockBeanFull>(new StringReader(sb.toString()))
407                     .withType(AnnotatedMockBeanFull.class)
408                     .withMappingStrategy(map)
409                     .build()
410                     .parse();
411             fail("An exception should have been thrown.");
412         } catch (RuntimeException re) {
413             Throwable t = re.getCause();
414             assertNotNull(t);
415             assertTrue(t instanceof CsvRequiredFieldEmptyException);
416         }
417     }
418 
419     @Test
420     public void bug154WhenUsingIteratorTheLineNumbersInTheExceptionShouldBePopulated() {
421         String data = "a,b\n" +
422                 "P,1\n" +
423                 "Q,12\n" +
424                 "R,1a\n" +
425                 "S,1b";
426         CsvToBean<Bug154Bean> c = new CsvToBeanBuilder<Bug154Bean>(new StringReader(data))
427                 .withType(Bug154Bean.class)
428                 .withThrowExceptions(false)
429                 .withErrorLocale(Locale.ROOT)
430                 .build();
431         for (Bug154Bean mockBean : c) {
432             System.out.println(mockBean.toString());
433         }
434         assertEquals(2, c.getCapturedExceptions().size());
435         CsvException exception1 = c.getCapturedExceptions().get(0);
436         assertEquals(4, exception1.getLineNumber());
437         assertNotNull(exception1.getLine());
438         CsvException exception2 = c.getCapturedExceptions().get(1);
439         assertEquals(5, exception2.getLineNumber());
440         assertNotNull(exception2.getLine());
441     }
442 
443     /**
444      * Tests use of a single bean verifier.
445      * <p>Also incidentally tests:</p>
446      * <ul><li>Adding {@code null} as a verifier before adding other
447      * verifiers.</li>
448      * <li>A verifier that discards beans.</li>
449      * <li>A verifier that verifies beans.</li></ul>
450      */
451     @Test
452     public void testSingleVerifier() {
453         List<SingleNumber> beans = new CsvToBeanBuilder<SingleNumber>(new StringReader(GOOD_NUMBERS))
454                 .withType(SingleNumber.class)
455                 .withVerifier(null)
456                 .withVerifier(new PositiveEvensOnly())
457                 .withOrderedResults(true)
458                 .build().parse();
459         assertNotNull(beans);
460         assertEquals(3, beans.size());
461         assertEquals(0, beans.get(0).getNumber());
462         assertEquals(2, beans.get(1).getNumber());
463         assertEquals(4, beans.get(2).getNumber());
464     }
465 
466     /**
467      * Tests that multiple verifiers work together.
468      * <p>Also incidentally tests:</p>
469      * <ul><li>Adding {@code null} as a verifier after other verifiers.</li></ul>
470      */
471     @Test
472     public void testMultipleVerifiers() {
473         List<SingleNumber> beans = new CsvToBeanBuilder<SingleNumber>(new StringReader(GOOD_NUMBERS))
474                 .withType(SingleNumber.class)
475                 .withVerifier(new PositiveEvensOnly())
476                 .withVerifier(new PositiveOddsOnly())
477                 .withVerifier(null)
478                 .build().parse();
479         assertNotNull(beans);
480         assertTrue(beans.isEmpty());
481     }
482 
483     @Test
484     public void testNullVerifierClearsList() {
485         CsvToBean<SingleNumber> csvToBean = new CsvToBeanBuilder<SingleNumber>(new StringReader(GOOD_NUMBERS))
486                 .withType(SingleNumber.class)
487                 .withVerifier(new PositiveEvensOnly())
488                 .withVerifier(new PositiveOddsOnly())
489                 .withOrderedResults(true)
490                 .build();
491         csvToBean.setVerifiers(null);
492         List<SingleNumber> beans = csvToBean.parse();
493         assertNotNull(beans);
494         assertEquals(5, beans.size());
495         assertEquals(0, beans.get(0).getNumber());
496         assertEquals(1, beans.get(1).getNumber());
497         assertEquals(2, beans.get(2).getNumber());
498         assertEquals(3, beans.get(3).getNumber());
499         assertEquals(4, beans.get(4).getNumber());
500     }
501 
502     @Test
503     public void testVerifierThrowsExceptionCollected() {
504         CsvToBean<SingleNumber> csvToBean = new CsvToBeanBuilder<SingleNumber>(new StringReader(BAD_NUMBERS))
505                 .withType(SingleNumber.class)
506                 .withVerifier(new PositiveOddsOnly())
507                 .withThrowExceptions(false)
508                 .withOrderedResults(true)
509                 .build();
510         List<SingleNumber> beans = csvToBean.parse();
511         List<CsvException> exceptions = csvToBean.getCapturedExceptions();
512         assertNotNull(beans);
513         assertEquals(2, beans.size());
514         assertEquals(1, beans.get(0).getNumber());
515         assertEquals(3, beans.get(1).getNumber());
516         assertNotNull(exceptions);
517         assertEquals(1, exceptions.size());
518         assertTrue(exceptions.get(0) instanceof CsvConstraintViolationException);
519         CsvConstraintViolationException csve = (CsvConstraintViolationException) exceptions.get(0);
520         assertEquals(5, csve.getLineNumber());
521         assertNotNull(csve.getLine());
522     }
523 
524     @Test
525     public void testVerifierThrowsExceptionRethrown() {
526         try {
527             new CsvToBeanBuilder<SingleNumber>(new StringReader(BAD_NUMBERS))
528                     .withType(SingleNumber.class)
529                     .withVerifier(new PositiveOddsOnly())
530                     .withThrowExceptions(true)
531                     .withOrderedResults(true)
532                     .build().parse();
533 
534             fail("Expecting exception thrown in parse.");
535         } catch (RuntimeException re) {
536             Throwable e = re.getCause();
537             assertTrue(e instanceof CsvConstraintViolationException);
538             CsvConstraintViolationException csve = (CsvConstraintViolationException) e;
539             assertEquals(5, csve.getLineNumber());
540             assertNotNull(csve.getLine());
541         }
542     }
543 
544     @Test
545     public void testBug194() {
546         String testString = "name,id,orderNumber\n" +
547                 "1,\"foo\", 3\n" +
548                 "1,\"a \" string with a quote in the middle\", 3\n" +
549                 "1,\"bar\", 3";
550 
551         String expectedString = "Error parsing CSV line: 3, values: a \" string with a quote in the middle, 3\n" +
552                 "1,bar, 3\n";
553         StringReader stringReader = new StringReader(testString);
554 
555         CsvToBean<MockBean> csvToBean = new CsvToBeanBuilder<MockBean>(stringReader)
556                 .withType(MockBean.class)
557                 .withIgnoreLeadingWhiteSpace(true)
558                 .withQuoteChar('"')
559                 .withSeparator(',')
560                 .withThrowExceptions(true)
561                 .build();
562 
563         try {
564             csvToBean.parse();
565             fail("Expected exception to be thrown.");
566         } catch (Exception e) {
567             assertEquals(expectedString, e.getMessage());
568         }
569     }
570 }