321

プログラムでフォームを検証するために使用される単純な Bean の単体テストを作成しようとしています。Bean には注釈が付けられており、次@Componentを使用して初期化されるクラス変数があります。

@Value("${this.property.value}") private String thisProperty;

このクラス内の検証メソッドの単体テストを作成したいと考えていますが、可能であれば、プロパティ ファイルを使用せずに作成したいと考えています。これの背後にある私の理由は、プロパティ ファイルから取得している値が変更された場合、それがテスト ケースに影響を与えないようにしたいということです。私のテストケースは、値自体ではなく、値を検証するコードをテストしています。

テスト クラス内で Java コードを使用して Java クラスを初期化し、そのクラス内で Spring @Value プロパティを入力してから、それを使用してテストする方法はありますか?

このハウツーは近いようですが、まだプロパティファイルを使用しています。私はむしろそれがすべてJavaコードであることを望んでいます。

4

10 に答える 10

261

可能であれば、Spring Context なしでこれらのテストを作成しようとします。スプリングを使用せずにテストでこのクラスを作成すると、そのフィールドを完全に制御できます。

フィールドを設定するには、 @valueSprings を使用できます。プライベート フィールドを設定ReflectionTestUtilsするメソッドがあります。setField

@see JavaDoc: ReflectionTestUtils.setField(java.lang.Object, java.lang.String, java.lang.Object)

于 2013-06-28T00:55:06.853 に答える
56

必要に応じて、Spring コンテキスト内でテストを実行し、Spring 構成クラス内で必要なプロパティを設定できます。JUnit を使用する場合は、SpringJUnit4ClassRunner を使用し、次のようにテスト専用の構成クラスを定義します。

テスト中のクラス:

@Component
public SomeClass {

    @Autowired
    private SomeDependency someDependency;

    @Value("${someProperty}")
    private String someProperty;
}

テストクラス:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = SomeClassTestsConfig.class)
public class SomeClassTests {

    @Autowired
    private SomeClass someClass;

    @Autowired
    private SomeDependency someDependency;

    @Before
    public void setup() {
       Mockito.reset(someDependency);

    @Test
    public void someTest() { ... }
}

そして、このテストの構成クラス:

@Configuration
public class SomeClassTestsConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() throws Exception {
        final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
        Properties properties = new Properties();

        properties.setProperty("someProperty", "testValue");

        pspc.setProperties(properties);
        return pspc;
    }
    @Bean
    public SomeClass getSomeClass() {
        return new SomeClass();
    }

    @Bean
    public SomeDependency getSomeDependency() {
        // Mockito used here for mocking dependency
        return Mockito.mock(SomeDependency.class);
    }
}

そうは言っても、このアプローチはお勧めしません。参考のためにここに追加しました。私の意見では、Mockito ランナーを使用する方がはるかに良い方法です。その場合、Spring 内でテストをまったく実行しません。これは、はるかに明確で単純です。

于 2014-11-20T11:53:03.420 に答える
32

まだ少し冗長ですが、これはうまくいくようです(もっと短いものが欲しいです):

@BeforeClass
public static void beforeClass() {
    System.setProperty("some.property", "<value>");
}

// Optionally:
@AfterClass
public static void afterClass() {
    System.clearProperty("some.property");
}
于 2015-08-10T06:03:13.123 に答える
5

構成に PropertyPlaceholderConfigurer を追加すると、うまくいきます。

@Configuration
@ComponentScan
@EnableJpaRepositories
@EnableTransactionManagement
public class TestConfiguration {
    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        builder.setType(EmbeddedDatabaseType.DERBY);
        return builder.build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan(new String[] { "com.test.model" });
        // Use hibernate
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
        entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
        return entityManagerFactoryBean;
    }

    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.show_sql", "false");
        properties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
        properties.put("hibernate.hbm2ddl.auto", "update");
        return properties;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
         transactionManager.setEntityManagerFactory(
              entityManagerFactory().getObject()
         );

         return transactionManager;
    }

    @Bean
    PropertyPlaceholderConfigurer propConfig() {
        PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer();
        placeholderConfigurer.setLocation(new ClassPathResource("application_test.properties"));
        return placeholderConfigurer;
    }
}

そしてテストクラスで

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
public class DataServiceTest {

    @Autowired
    private DataService dataService;

    @Autowired
    private DataRepository dataRepository;

    @Value("${Api.url}")
    private String baseUrl;

    @Test
    public void testUpdateData() {
        List<Data> datas = (List<Data>) dataRepository.findAll();
        assertTrue(datas.isEmpty());
        dataService.updateDatas();
        datas = (List<Data>) dataRepository.findAll();
        assertFalse(datas.isEmpty());
    }
}
于 2015-09-14T21:30:43.783 に答える
3
@ExtendWith(SpringExtension.class)    // @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class)

それが助けになるかもしれません。重要なのは、ConfigDataApplicationContextInitializer がすべての props データを取得することです

于 2021-02-07T20:46:31.117 に答える
-6

Spring Boot は多くのことを自動的に行いますが、アノテーション@SpringBootTestを使用すると、Spring Boot によってすべてが自動的に解決されると考えられます。

多くのドキュメントがありますが、最小限の方法は、1 つのエンジンを選択し( @RunWith(SpringRunner.class))、使用されるクラスを指定して、構成をロードするためのコンテキストresources/applicationl.propertiesを作成することです ( )。

簡単に言えば、エンジンコンテキストが必要です。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyClassTest .class)
public class MyClassTest {

    @Value("${my.property}")
    private String myProperty;

    @Test
    public void checkMyProperty(){
        Assert.assertNotNull(my.property);
    }
}

もちろん、Spring Boot のドキュメントを見ると、それを行うための何千もの OS の方法が見つかります。

于 2020-07-24T12:53:35.250 に答える