Reputation:
I am new in JUnittesting so i have a question. Can anyone please tell me why we use ReflectionTestUtils.setField()
in our Junit testing with example.
Upvotes: 23
Views: 96322
Reputation: 4539
One more Use Case:
As a best practice we externalised many properties that we want change in application when thwty are subject to change. Such as: URL's , endpoint and many other properties in application properties like below:
kf.get.profile.endpoint=/profile
kf.get.clients.endpoint=clients
and then these config we can use it in application like below using @Value annotation:
@Value("${kf.get.clients.endpoint}")
private String clientEndpoint
but these values we cannot easily set in unit tests because for encapsulation purpose we should be keep these values as private. therefore whenevver when we write unit test , we get NullPointerException because Spring cannot inject @value similarly as @Autowired does. ( at least at the moment , I dont know alternative. ) so to avoid that we can use ReflectionTestUtils to inject externalised properties. like below:
ReflectionTestUtils.setField(targetObject,"clientEndpoint","lorem");
Upvotes: 7
Reputation: 13
ReflectionTestUtils.setField
is used is various contexts. But the most common scenario is when you have a class and inside that, there are attributes with private access, and you want to test this class.
So a possible solution can be using ReflectionTestUtils
like in the example below:
public class BBVAFileProviderTest {
@Mock
private BBVAFileProvider bbvaFileProvider;
@Before
public void setup() throws Exception {
bbvaFileProvider = new BBVAFileProvider(payoutFileService, bbvaFileAdapter, bbvaCryptographyService, amazonS3Client, providerRequestService, payoutConfirmationService);
ReflectionTestUtils.setField(this.bbvaFileProvider, "bbvaClient", this.bbvaClient);
}
// ...
}
In this example can you see, that ReflectionTestUtils.setField
is used to set the value to the private field because it doesn't have a setter method.
Upvotes: -1
Reputation: 12734
As mentioned in the comment, the java docs explain the usage well. But I want to give you also a simple example.
Let's say you have an Entity class with private or protected field access and no provided setter method.
@Entity
public class MyEntity {
@Id
private Long id;
public Long getId(Long id){
this.id = id;
}
}
In your test class, you cannot set an id
of your entity
because of the missing setter method.
Using ReflectionTestUtils.setField
you are able to do that for testing purpose:
ReflectionTestUtils.setField(myEntity, "id", 1);
The Parameters are described:
public static void setField(Object targetObject,
String name,
Object value)
Set the field with the given name on the provided targetObject to the supplied value.
This method delegates to setField(Object, String, Object, Class), supplying null for the type argument.
Parameters:
targetObject - the target object on which to set the field; never null
name - the name of the field to set; never null
value - the value to set
But give it a try and read the docs.
Upvotes: 32
Reputation: 11
Thank you for above discussions, the below part can also contribute in writing the unit tests by reading the properties from application-test.properties.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestPropertySource("classpath:application-test.properties")
public class FileRetrivalServiceTest {
@Value ("${fs.local.quarantine.directory}")
private String localQuarantineDirectory;
@Value ("${fs.local.quarantine.wrong.directory}")
private String localQuarantineWrongDirectory;
@Value ("${fs.local.quarantine.tmp.directory}")
private String localQuarantineTmpDirectory;
@Value ("${fs.local.keys.file}")
private String localKeyFile;
private FileRetrivalService fileRetrivalService;
@Before
public void setUp() throws Exception {
fileRetrivalService = new FileRetrivalServiceImpl();
ReflectionTestUtils.setField(fileRetrivalService, "keyFile", localKeyFile);
}
@Test
public void shouldRetrieveListOfFilesInQuarantineDirectory() {
// given
ReflectionTestUtils.setField(fileRetrivalService, "quarantineDirectory", localQuarantineDirectory);
// when
List<IcrFileModel> quarantineFiles = fileRetrivalService.retrieveListOfFilesInQuarantineDirectory();
// then
assertNotNull(quarantineFiles);
assertEquals(quarantineFiles.size(), 4);
}
}
Upvotes: 1
Reputation: 21
it's very useful when we want to write unit test, such as:
class A{
int getValue();
}
class B{
A a;
int caculate(){
...
int v = a.getValue();
....
}
}
class ServiceTest{
@Test
public void caculateTest(){
B serviceB = new B();
A serviceA = Mockito.mock(A.class);
Mockito.when(serviceA.getValue()).thenReturn(5);
ReflectionTestUtils.setField(serviceB, "a", serviceA);
}
}
Upvotes: 2