Spring Boot单元测试中的模拟@Value不起作用
Mock @Value in SpringBoot unit test not working
我正在尝试使用 Mockito 进行一些 junit 测试以在 SprinBoot 应用程序中工作。
现在我的服务有一些变量通过 @Value
注释从 application.properties
中填充:
@Component
@Slf4j
public class FeatureFlagService {
@Autowired
RestTemplate restTemplate;
@Value("${url.feature_flags}")
String URL_FEATURE_FLAGS;
// do stuff
}
我正在尝试使用 TestPropertySource
来测试它,如下所示:
@ExtendWith(MockitoExtension.class)
@TestPropertySource(properties = { "${url.feature_flags} = http://endpoint" })
class FeatureFlagServiceTests {
@Mock
RestTemplate restTemplate;
@InjectMocks
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}
但是 属性 没有被填满,仍然是 null
。
有很多关于这个的问题,但我还没有能够拼凑出一个解决方案。我看到建议 @SpringBootTest
的解决方案,但它似乎想要进行集成测试,启动服务,但由于无法连接到数据库而失败。所以这不是我要找的。
我还看到建议我制作一个 PropertySourcesPlaceholderConfigurer
bean 的解决方案。
我尝试通过放置 :
@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
在我的Application.java
。但这不起作用/不够。我不确定我是否应该做不同的事情,或者是否还有更多我不知道的事情。
请指教
我推荐你试试这个方法。只需要稍微重构并向 FeatureFlagService
.
添加一个 package-private 构造函数
FeatureFlagService.java
@Component
@Slf4j
public class FeatureFlagService {
private final RestTemplate restTemplate;
private final String URL_FEATURE_FLAGS;
// package-private constructor. test-only
FeatureFlagService(RestTemplate restTemplate, @Value("${url.feature_flags}") String flag) {
this.restTemplate = restTemplate;
this.URL_FEATURE_FLAGS = flag;
}
// do stuff
}
然后准备你的 mocks 和 url,并通过 constructor-injection
.
注入它们
FeatureFlagServiceTests.java
public class FeatureFlagServiceTests {
private FeatureFlagService featureFlagService;
@Before
public void setup() {
RestTemplate restTemplate = mock(RestTemplate.class);
// when(restTemplate)...then...
String URL_FEATURE_FLAGS = "http://endpoint";
featureFlagService = new FeatureFlagService(restTemplate, URL_FEATURE_FLAGS);
}
@Test
public void propertyTest(){
Assertions.assertEquals(featureFlasgService.getUrlFeatureFlags(),
"http://endpoint");
}
}
显着的优势是,您的 FeatureFlagServiceTests
变得非常易于阅读和测试。您不再需要 Mockito 的神奇注释。
您可以在没有 运行 整个应用程序的情况下使用 @SpringBootTest
,方法是将其传递给包含 @Value
的 class,但您必须使用 Spring' s extension @ExtendWith({SpringExtension.class})
包含在 @SpringBootTest
中,并且使用 Spring 的 MockBean
而不是 @Mock
和 @Autowired
来自动装配 bean,例如这个:
@SpringBootTest(classes = FeatureFlagService.class)
class FeatureFlagServiceTests {
@MockBean
RestTemplate restTemplate;
@Autowired
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}
我正在尝试使用 Mockito 进行一些 junit 测试以在 SprinBoot 应用程序中工作。
现在我的服务有一些变量通过 @Value
注释从 application.properties
中填充:
@Component
@Slf4j
public class FeatureFlagService {
@Autowired
RestTemplate restTemplate;
@Value("${url.feature_flags}")
String URL_FEATURE_FLAGS;
// do stuff
}
我正在尝试使用 TestPropertySource
来测试它,如下所示:
@ExtendWith(MockitoExtension.class)
@TestPropertySource(properties = { "${url.feature_flags} = http://endpoint" })
class FeatureFlagServiceTests {
@Mock
RestTemplate restTemplate;
@InjectMocks
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}
但是 属性 没有被填满,仍然是 null
。
有很多关于这个的问题,但我还没有能够拼凑出一个解决方案。我看到建议 @SpringBootTest
的解决方案,但它似乎想要进行集成测试,启动服务,但由于无法连接到数据库而失败。所以这不是我要找的。
我还看到建议我制作一个 PropertySourcesPlaceholderConfigurer
bean 的解决方案。
我尝试通过放置 :
@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
在我的Application.java
。但这不起作用/不够。我不确定我是否应该做不同的事情,或者是否还有更多我不知道的事情。
请指教
我推荐你试试这个方法。只需要稍微重构并向 FeatureFlagService
.
FeatureFlagService.java
@Component
@Slf4j
public class FeatureFlagService {
private final RestTemplate restTemplate;
private final String URL_FEATURE_FLAGS;
// package-private constructor. test-only
FeatureFlagService(RestTemplate restTemplate, @Value("${url.feature_flags}") String flag) {
this.restTemplate = restTemplate;
this.URL_FEATURE_FLAGS = flag;
}
// do stuff
}
然后准备你的 mocks 和 url,并通过 constructor-injection
.
FeatureFlagServiceTests.java
public class FeatureFlagServiceTests {
private FeatureFlagService featureFlagService;
@Before
public void setup() {
RestTemplate restTemplate = mock(RestTemplate.class);
// when(restTemplate)...then...
String URL_FEATURE_FLAGS = "http://endpoint";
featureFlagService = new FeatureFlagService(restTemplate, URL_FEATURE_FLAGS);
}
@Test
public void propertyTest(){
Assertions.assertEquals(featureFlasgService.getUrlFeatureFlags(),
"http://endpoint");
}
}
显着的优势是,您的 FeatureFlagServiceTests
变得非常易于阅读和测试。您不再需要 Mockito 的神奇注释。
您可以在没有 运行 整个应用程序的情况下使用 @SpringBootTest
,方法是将其传递给包含 @Value
的 class,但您必须使用 Spring' s extension @ExtendWith({SpringExtension.class})
包含在 @SpringBootTest
中,并且使用 Spring 的 MockBean
而不是 @Mock
和 @Autowired
来自动装配 bean,例如这个:
@SpringBootTest(classes = FeatureFlagService.class)
class FeatureFlagServiceTests {
@MockBean
RestTemplate restTemplate;
@Autowired
FeatureFlagService featureFlasgService;
@Test
void propertyTest(){
Assertions.assertEquals(featureFlasgService.URL_FEATURE_FLAGS, "http://endpoint");
}