mockito SpringBoot单元测试中的Mock @Values 不起作用

kse8i1jr  于 2022-11-08  发布在  Spring
关注(0)|答案(2)|浏览(511)

我正在尝试用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
有一堆关于这个的tpoics,但我还没有能够拼凑出一个解决方案。我看到建议@SpringBootTest的解决方案,但后来它似乎想做一个集成测试,启动服务,失败了,因为它无法连接到DB。所以这不是我要找的。
我还看到了一些建议我制作一个PropertySourcesPlaceholderConfigurer bean的解决方案。我试着这样做:

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

在我的Application.java中。但是这是不起作用的/不够的。我不确定我是否应该以不同的方式这样做,或者是否有更多的东西我不知道。
请多多指教。

56lgkhnf

56lgkhnf1#

您可以通过将包含@Value的类传递给它来使用@SpringBootTest,而无需运行整个应用程序,但您必须使用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");
  }
hjzp0vay

hjzp0vay2#

我建议你试试这个方法,只需要稍微重构一下,在你的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注入它们。

功能标志服务测试.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的神奇注解。

相关问题