简体   繁体   English

SpringBoot单元测试中的模拟@Value不起作用

[英]Mock @Value in SpringBoot unit test not working

I am trying to get some junit tests with Mockito to work in a SprinBoot application.我正在尝试使用 Mockito 进行一些 junit 测试,以便在 SprinBoot 应用程序中工作。

Now my Service has some variable that gets filled from the application.properties by means of @Value annotation:现在我的服务有一些变量,通过@Value注释从application.properties中填充:

@Component
@Slf4j
public class FeatureFlagService {

  @Autowired
  RestTemplate restTemplate;

  @Value("${url.feature_flags}")
  String URL_FEATURE_FLAGS;

// do stuff
}

I am trying to test this by using TestPropertySource like so:我正在尝试像这样使用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");
  }

However the property does not get filled and remains null .但是,该属性未被填充并保持null

There are a bunch of tpoics on this, but I have not been able to piece together a solution.这方面有很多问题,但我无法拼凑出一个解决方案。 I saw solutions suggesting @SpringBootTest , but then it seems to want to do an integration test, spinning up the service, which fails because it can not connect to DB.我看到建议@SpringBootTest的解决方案,但随后它似乎想要进行集成测试,启动服务,但由于无法连接到数据库而失败。 So that is not what I am looking for.所以这不是我要找的。

I also saw solutions suggesting I make a PropertySourcesPlaceholderConfigurer bean.我还看到了建议我制作PropertySourcesPlaceholderConfigurer bean 的解决方案。 I tried that by putting:我尝试通过放置:

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

In my Application.java .在我的Application.java中。 But that is not working / not enough.但这不起作用/不够。 I am not sure if I was supposed to do that differently, or if there is more there that I do not know.我不确定我是否应该做不同的事情,或者是否还有更多我不知道的事情。

Please advice.请指教。

You can use @SpringBootTest without running the whole application by passing it the class that contains the @Value but you have to use Spring's extension @ExtendWith({SpringExtension.class}) which is included inside @SpringBootTest and by that using Spring's MockBean instead of @Mock and @Autowired for autowiring the bean like this:您可以使用@SpringBootTest而无需运行整个应用程序,方法是将它传递给包含 @Value 的@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");
  }

I recommend you to try this approach.我建议您尝试这种方法。 Just need a slightly refactoring and add a package-private constructor to your FeatureFlagService .只需要稍微重构并向您的FeatureFlagService添加一个包私有构造函数。

FeatureFlagService.java 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
}

Then prepare your mocks and url, and inject them by the constructor-injection .然后准备你的 mocks 和 url,并通过constructor-injection注入它们。

FeatureFlagServiceTests.java 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");
    }
}

The significant advantage is, your FeatureFlagServiceTests becomes very simple to read and trivial to test.显着的优势是,您的FeatureFlagServiceTests变得非常易于阅读和测试。 You don't need magic annotation of Mockito anymore.您不再需要 Mockito 的神奇注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM