简体   繁体   中英

Spring ReflectionTestUtils does not set primitive data type field

I use ReflectionTestUtils to set int field in my service class to test the class. My service class like:

@Service
public class SampleService {

    @Value("${app.count}")
    private int count;

    @Value("${app.countStr}")
    private String countStr;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public String getCountStr() {
        return countStr;
    }

    public void setCountStr(String countStr) {
        this.countStr = countStr;
    }

    @PostConstruct
    public int demoMethod() {
        return count + Integer.parseInt(countStr);
    }
}

and test class is like:

@RunWith(SpringRunner.class)
public class SampleServiceTest {

    @Autowired
    private SampleService sampleService;

    @TestConfiguration
    static class SampleServiceTestConfig {

        @Bean
        public SampleService sampleService() {
            return new SampleService();
        }
    }

    @Before
    public void init() {
        ReflectionTestUtils.setField(sampleService, "count", new Integer(100));
        ReflectionTestUtils.setField(sampleService, "countStr", 100);
    }

    @Test
    public void testDemoMethod() {
        int a  = sampleService.demoMethod();
        Assert.assertTrue(a == 200);
    }
}

While I run this test case it gives below error:

Caused by: java.lang.NumberFormatException: For input string: "${app.count}"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:569)
    at java.lang.Integer.valueOf(Integer.java:766)
    at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:210)
    at org.springframework.beans.propertyeditors.CustomNumberEditor.setAsText(CustomNumberEditor.java:115)
    at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:466)
    at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:439)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:192)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:117)
    at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:70)
    ... 47 more

Why ReflectionTestUtils try set string value in the field?

I put 2 fields, one is an integer and another is a string for testing purpose.

You can find source code here .

Please have look and suggest a workaround for the same.

Your problem is that the method annotated with @Before is invoked after that the spring context was initialized and that the service was injected by Spring in your test class.
Which means that these two fields :

@Value("${app.count}")
private int count;

@Value("${app.countStr}")
private String countStr;

will have as value the value defined in their @Value values.
String countStr can be valued with the "${app.countStr}" String (even it it makes no sense).
But int count cannot be valued with the "${app.count}" String as "${app.count}" cannot be converted into an int value .
Whereas the thrown exception as Integer.parseInt("${app.count}") is invoked :

Caused by: java.lang.NumberFormatException: For input string: "${app.count}"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:569)

To address this issue, use @TestPropertySource as suggested by Nisheeth Shah to provide the value for the properties at the suitable time.

As a general advise, limit the reflection use. It is checked only at runtime and that is often more opaque.

While testing, you have to provide properties source. If you don't add properties, it will inject the value inside @Value in the variable. In your case, it tries to add the string in the integer that gives NumberFormatException . Try adding as below:

@RunWith(SpringRunner.class)
@TestPropertySource(properties = {"app.count=1", "app.countStr=sampleString"})
public class SampleServiceTest{...}

I hope it helps.

As you are using @Autowired , before ReflectionTestUtils it tries to add the value inside @Value .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM