setField()在Junit测试中的使用

vvppvyoh  于 2022-11-11  发布在  其他
关注(0)|答案(5)|浏览(180)

我是JUnittesting的新手,所以我有一个问题。有人能告诉我为什么我们在JUnit测试中使用ReflectionTestUtils.setField()吗?

oymdgrw7

oymdgrw71#

正如在评论中提到的,java文档很好地解释了用法。但我也想给予你一个简单的例子。
假设您有一个具有私有或受保护字段访问权限的Entity类,并且没有提供setter方法

@Entity
public class MyEntity {

   @Id
   private Long id;

   public Long getId(Long id){
       this.id = id;
   }
}

在测试类中,由于缺少setter方法,因此无法设置entityid
使用ReflectionTestUtils.setField,您可以执行此操作以进行测试:

ReflectionTestUtils.setField(myEntity, "id", 1);

参数描述如下:

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

但是给予一试,读一读docs

gstyhher

gstyhher2#

另一个使用案例:
我们具体化了许多属性,例如:应用程序属性中的URL、端点和许多其他属性,如下所示:

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

然后将其用于如下应用中:

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

每当我们编写单元测试时,我们都会得到NullPointerException,因为Spring不能像@Autowired那样注入@value。(至少目前,我不知道替代方法。)因此,为了避免这种情况,我们可以使用ReflectionTestUtils来注入外部化属性。如下所示:

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

mrfwxfqh3#

当我们要编写单元测试时,它非常有用,例如:

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

amrnrhlw4#

感谢您的上述讨论,下面的部分也可以通过阅读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);
    }
}
8wigbo56

8wigbo565#

ReflectionTestUtils.setField被用于各种上下文,但最常见的情况是当你有一个类,里面有私有访问的属性,你想测试这个类.
因此,一个可能的解决方案是使用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);
    }

    // ...

}

在这个例子中,你可以看到,ReflectionTestUtils.setField被用来设置私有字段的值,因为它没有setter方法。

相关问题