简体   繁体   English

在 Junit 测试中使用 ReflectionTestUtils.setField()

[英]Use of ReflectionTestUtils.setField() in Junit testing

I am new in JUnittesting so i have a question.我是 JUnittesting 的新手,所以我有一个问题。 Can anyone please tell me why we use ReflectionTestUtils.setField() in our Junit testing with example.谁能告诉我为什么我们在 Junit 测试中使用ReflectionTestUtils.setField()示例。

As mentioned in the comment, the java docs explain the usage well.正如评论中提到的,java 文档很好地解释了用法。 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 类,并且没有提供 setter 方法

@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.在您的测试类中,由于缺少 setter 方法,您无法设置entityid

Using ReflectionTestUtils.setField you are able to do that for testing purpose:使用ReflectionTestUtils.setField您可以出于测试目的执行此操作:

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 .但试一试并阅读文档

One more Use Case:另一个用例:

We externalised many properties Such as: URL's , endpoint and many other properties in application properties like below:我们外部化了许多属性,例如:URL、端点和应用程序属性中的许多其他属性,如下所示:

kf.get.profile.endpoint=/profile
kf.get.clients.endpoint=clients

and then use it in application like below:然后在应用程序中使用它,如下所示:

  @Value("${kf.get.clients.endpoint}")
  private String getClientEndpoint

and whenever when we write unit test , we get NullPointerException because Spring cannot inject @value similarly as @Autowired does.每当我们编写 unit test 时,我们都会得到NullPointerException ,因为 Spring 不能像 @Autowired 那样注入 @value 。 ( at least at the moment , I dont know alternative. ) so to avoid that we can use ReflectionTestUtils to inject externalised properties. (至少目前,我不知道替代方案。)所以为了避免我们可以使用ReflectionTestUtils来注入外部属性。 like below:如下所示:

ReflectionTestUtils.setField(targetObject,"getClientEndpoint","lorem");

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);
   } 
}

Thank you for above discussions, the below part can also contribute in writing the unit tests by reading the properties from application-test.properties.感谢您的上述讨论,以下部分还可以通过读取 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);
    }
}

ReflectionTestUtils.setField is used is various context. ReflectionTestUtils.setField 用于各种上下文。 But the most common scenario is when you have a class and inside that, there are attributes with private access, So you want to do test file to this class.但最常见的情况是当你有一个 class 并且里面有私有访问的属性,所以你想对这个 class 做测试文件。

So a solution posible can be ReflectionTestUtils how is the next example below:因此,可能的解决方案是 ReflectionTestUtils 下面的下一个示例如何:

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 these example can you see that is used ReflectionTestUtils.setField to set the value to the field private because it don't have setter method.在这些示例中,您可以看到使用 ReflectionTestUtils.setField 将值设置为私有字段,因为它没有 setter 方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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