Mock @Value在SpringBoot单元测试中不起作用



我正在尝试使用Mockito在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的解决方案,但随后它似乎想要做一个集成测试,旋转服务,因为它无法连接到DB而失败。所以这不是我想要的。

我也看到解决方案建议我做一个PropertySourcesPlaceholderConfigurerbean。我试着输入:

@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}

在我的Application.java。但这还不够。我不确定我是否应该这样做,或者是否还有更多我不知道的。

请建议。

您可以使用@SpringBootTest而不运行整个应用程序,通过传递包含@Value的类,但您必须使用Spring的扩展@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");
}

我建议您尝试这种方法。只需要稍微重构一下,并在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
}

然后准备你的mock和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的魔法注释了。

最新更新