无法在 JUnit 5 中使用 @Value 获取属性值
Unable to fetch properties value using @Value in JUnit 5
在我的服务实现中 class 我正在尝试使用 @Value 从 application.properties 获取值。它工作正常。但是在为其编写测试用例时,我得到了 null。
内部服务实现 class
@Value("${transaction.service.process.layer.url}")
private String processLayerUrl;
public ResponseEntity<Object> getTransactionDataListByAccount(Transaction transaction) {
ResponseEntity<Object> transactionHistoryResponse = restTemplate.postForEntity(processLayerUrl, transaction, Object.class);
return new ResponseEntity<>(transactionHistoryResponse.getBody(), HttpStatus.OK);
}
测试文件
@RunWith(SpringRunner.class)
@WebMvcTest(value = TransactionServiceImpl.class)
@ActiveProfiles(profiles = "test")
@ContextConfiguration
//@ContextConfiguration(classes = TransactionServiceExperienceApplication.class)
//@SpringBootConfiguration(classes = { TransactionServiceExperienceApplicationTests.class })
//@TestPropertySource(locations="classpath:application-test.properties")
//@SpringBootTest(properties = { "transaction.service.process.layer.url =http://localhost:8087/v1/transaction-process-service" })
//@TestPropertySource(properties = { "transaction.service.process.layer.url = http://localhost:8087/v1/transaction-process-service" })
public class TransactionServiceImplTest {
@Mock
private RestTemplate mockRestTemplate;
@InjectMocks
private TransactionServiceImpl transactionService;
@Before
public void setUp() {
//transactionService = new TransactionServiceImpl("test");
//ReflectionTestUtils.setField(transactionService, "processLayerUrl", "foo");
}
@Test
public void getTransactionDataListByAccountTest() throws Exception{
Transaction transaction = new Transaction();
transaction.setPosAccountNumber("40010020070401");
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
ArrayList<Object> mockResponseObj = new ArrayList<Object>();
//Added data inside this object
ResponseEntity<Object> responseEntity = new ResponseEntity<>(mockResponseObj, HttpStatus.OK);
when(mockRestTemplate.postForEntity(
ArgumentMatchers.anyString(),
ArgumentMatchers.eq(Transaction.class),
ArgumentMatchers.eq(Object.class))).thenReturn(responseEntity);
ResponseEntity<Object> actualResponse = transactionService.getTransactionDataListByAccount(transaction);
System.out.println("--- Response ---");
System.out.println(actualResponse);
}
/*
* @Configuration
*
* @ComponentScan("transaction.service.experience.service") static class
* someConfig {
*
* // because @PropertySource doesnt work in annotation only land
*
* @Bean PropertySourcesPlaceholderConfigurer propConfig() {
* PropertySourcesPlaceholderConfigurer ppc = new
* PropertySourcesPlaceholderConfigurer(); ppc.setLocation(new
* ClassPathResource("application.properties")); return ppc; } }
*/
}
我在src/test/resources
中指定了应用程序-test.properties文件
这是我的 build.gradle
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
implementation 'junit:junit:4.12'
由于这个 restTemplate 抛出 NullPointerException 而不是返回 mock obj。
发生这种情况是因为您使用的是 Mockito 注释,而不是 Spring Boot 提供的注释。
transactionService
应注释为 @Autowired
,mockRestTemplate
应注释为 @MockBean
。
@MockBean
在 Spring 应用程序上下文中添加或替换原始 bean,并将其注入到此上下文中需要它作为依赖项的任何 bean。
如果您编写的测试是集成测试,则不应手动实例化 transactionService。
您还应该重新考虑您在这里测试的是什么 - WebMvc 测试旨在测试控制器,而不是服务。如果你想测试服务 - 考虑编写不涉及 Spring 的普通单元测试。如果您想要真正的集成测试,请考虑使用 @SpringBootTest
.
在我的服务实现中 class 我正在尝试使用 @Value 从 application.properties 获取值。它工作正常。但是在为其编写测试用例时,我得到了 null。
内部服务实现 class
@Value("${transaction.service.process.layer.url}")
private String processLayerUrl;
public ResponseEntity<Object> getTransactionDataListByAccount(Transaction transaction) {
ResponseEntity<Object> transactionHistoryResponse = restTemplate.postForEntity(processLayerUrl, transaction, Object.class);
return new ResponseEntity<>(transactionHistoryResponse.getBody(), HttpStatus.OK);
}
测试文件
@RunWith(SpringRunner.class)
@WebMvcTest(value = TransactionServiceImpl.class)
@ActiveProfiles(profiles = "test")
@ContextConfiguration
//@ContextConfiguration(classes = TransactionServiceExperienceApplication.class)
//@SpringBootConfiguration(classes = { TransactionServiceExperienceApplicationTests.class })
//@TestPropertySource(locations="classpath:application-test.properties")
//@SpringBootTest(properties = { "transaction.service.process.layer.url =http://localhost:8087/v1/transaction-process-service" })
//@TestPropertySource(properties = { "transaction.service.process.layer.url = http://localhost:8087/v1/transaction-process-service" })
public class TransactionServiceImplTest {
@Mock
private RestTemplate mockRestTemplate;
@InjectMocks
private TransactionServiceImpl transactionService;
@Before
public void setUp() {
//transactionService = new TransactionServiceImpl("test");
//ReflectionTestUtils.setField(transactionService, "processLayerUrl", "foo");
}
@Test
public void getTransactionDataListByAccountTest() throws Exception{
Transaction transaction = new Transaction();
transaction.setPosAccountNumber("40010020070401");
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
ArrayList<Object> mockResponseObj = new ArrayList<Object>();
//Added data inside this object
ResponseEntity<Object> responseEntity = new ResponseEntity<>(mockResponseObj, HttpStatus.OK);
when(mockRestTemplate.postForEntity(
ArgumentMatchers.anyString(),
ArgumentMatchers.eq(Transaction.class),
ArgumentMatchers.eq(Object.class))).thenReturn(responseEntity);
ResponseEntity<Object> actualResponse = transactionService.getTransactionDataListByAccount(transaction);
System.out.println("--- Response ---");
System.out.println(actualResponse);
}
/*
* @Configuration
*
* @ComponentScan("transaction.service.experience.service") static class
* someConfig {
*
* // because @PropertySource doesnt work in annotation only land
*
* @Bean PropertySourcesPlaceholderConfigurer propConfig() {
* PropertySourcesPlaceholderConfigurer ppc = new
* PropertySourcesPlaceholderConfigurer(); ppc.setLocation(new
* ClassPathResource("application.properties")); return ppc; } }
*/
}
我在src/test/resources
中指定了应用程序-test.properties文件这是我的 build.gradle
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
implementation 'junit:junit:4.12'
由于这个 restTemplate 抛出 NullPointerException 而不是返回 mock obj。
发生这种情况是因为您使用的是 Mockito 注释,而不是 Spring Boot 提供的注释。
transactionService
应注释为 @Autowired
,mockRestTemplate
应注释为 @MockBean
。
@MockBean
在 Spring 应用程序上下文中添加或替换原始 bean,并将其注入到此上下文中需要它作为依赖项的任何 bean。
如果您编写的测试是集成测试,则不应手动实例化 transactionService。
您还应该重新考虑您在这里测试的是什么 - WebMvc 测试旨在测试控制器,而不是服务。如果你想测试服务 - 考虑编写不涉及 Spring 的普通单元测试。如果您想要真正的集成测试,请考虑使用 @SpringBootTest
.