datafaker-net / datafaker

Generating fake data for the JVM (Java, Kotlin, Groovy) has never been easier!
https://www.datafaker.net
Apache License 2.0
1.09k stars 151 forks source link

java.lang.ClassCastException for finance.credit_card provider with Enum argument in Faker expression #1274

Closed panilya closed 1 week ago

panilya commented 1 week ago

Describe the bug Datafaker throws java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap') exception on trying to generate creditCard with Enum argument (enum CreditCardType) using the Expression feature.

To Reproduce Faker().expression("#{finance.credit_card 'CreditCardType.MASTERCARD'}") throws java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String

Expected behavior Generated credit card number using the correct format based on the CreditCardType Enum argument defined in the finance.yml file.

Versions:

Additional context Stack trace:

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap')

    at net.datafaker.service.FakeValuesService.safeFetch(FakeValuesService.java:198)
    at net.datafaker.service.FakeValuesService.safeFetch(FakeValuesService.java:184)
    at net.datafaker.service.FakeValuesService.lambda$resolveExpression$15(FakeValuesService.java:820)
    at net.datafaker.service.FakeValuesService.resExp(FakeValuesService.java:750)
    at net.datafaker.service.FakeValuesService.resolveExpression(FakeValuesService.java:652)
    at net.datafaker.service.FakeValuesService.resolveExpression(FakeValuesService.java:624)
    at net.datafaker.service.FakeValuesService.expression(FakeValuesService.java:527)
    at net.datafaker.service.FakeValuesServiceTest.creditCardExpressionWithEnumArgument(FakeValuesServiceTest.java:304)
asolntsev commented 1 week ago

@panilya Are you sure such an expression is expected to work? Can you provide some similar working examples?

You can use the following syntax instead:

  assertThat(faker.expression("#{finance.credit_card.american_express}")).isNotBlank();
  assertThat(faker.expression("#{finance.credit_card.mastercard}")).isNotBlank();
panilya commented 1 week ago

I need to utilize expression arguments because expression strings are generated dynamically in my use case and unfortunately, expressions like this one: faker.expression("#{finance.credit_card.american_express}") won't work for me :(

For working examples, you can take a look at the unit tests located in the FakeValuesServiceTest.futureDateExpression() and FakeValuesServiceTest.pastDateExpression(). As you can see, those tests successfully utilize Enum expression arguments.

kingthorin commented 1 week ago

So does it work if you use a FakerValueService?

panilya commented 1 week ago

So does it work if you use a FakerValueService?

No. For example, a test like this one also doesn't work:

    @Test
    void creditCardExpressionWithEnumArgument() {
        assertThat(fakeValuesService.expression("#{finance.credit_card 'CreditCardType.MASTERCARD'}", faker, context))
            .isNotEmpty();
    }

Since expression(String expression, BaseFaker faker, FakerContext context) is called from BaseFaker.expression(String expression) - they are basically the same, so, I don't think outputs can be different.

kingthorin commented 1 week ago

I think I've found the issue. I'm just doing some testing and will hopefully PR a fix soon.