リフレクションによって取得/設定されるプライベートフィールドを乱用しないでください
ここでいくつかの回答で行われているようにリフレクションを使用することは、回避できるものです。
ここには小さな価値がありますが、複数の欠点があります。
- 実行時にのみリフレクションの問題を検出します(例:もはや存在しないフィールド)
- カプセル化が必要ですが、表示する必要のある依存関係を隠し、クラスをより不透明でテストしにくくする不透明なクラスは必要ありません。
- それは悪いデザインを奨励します。今日、宣言し
@Value String field
ます。明日あなたが宣言することができます5
または10
それらのそのクラスに、あなたも、あなたはクラスの設計を減らすことにまっすぐに認識していなくてもよいです。これらのフィールド(コンストラクターなど)を設定するためのより目に見えるアプローチでは、これらのすべてのフィールドを追加する前によく考えて、おそらくそれらを別のクラスにカプセル化して使用します@ConfigurationProperties
。
クラスを単一と統合の両方でテスト可能にする
Springコンポーネントクラスのプレーンテスト(つまり、実行中のSpringコンテナーなし)と統合テストの両方を記述できるようにするには、このクラスをSpringの有無にかかわらず使用できるようにする必要があります。
必要のないときに単体テストでコンテナーを実行することは、ローカルビルドの速度を低下させる悪い習慣です。これは望ましくありません。
ここでは答えがこの違いを示さないようで、実行中のコンテナーに体系的に依存しているため、この答えを追加しました。
したがって、クラスの内部として定義されているこのプロパティを移動する必要があると思います。
@Component
public class Foo{
@Value("${property.value}") private String property;
//...
}
Springによって注入されるコンストラクタパラメータに:
@Component
public class Foo{
private String property;
public Foo(@Value("${property.value}") String property){
this.property = property;
}
//...
}
単体テストの例
Foo
Springなしでインスタンス化property
し、コンストラクターのおかげで値を注入できます。
public class FooTest{
Foo foo = new Foo("dummyValue");
@Test
public void doThat(){
...
}
}
統合テストの例
のproperties
属性のおかげで、この簡単な方法でSpring Bootのコンテキストにプロパティを注入できます@SpringBootTest
。
@SpringBootTest(properties="property.value=dummyValue")
public class FooTest{
@Autowired
Foo foo;
@Test
public void doThat(){
...
}
}
代替として使用することもできます @TestPropertySource
が、追加の注釈が追加されます。
@SpringBootTest
@TestPropertySource("property.value=dummyValue")
public class FooTest{ ...}
Spring(Spring Bootなし)では少し複雑になりますが、Spring BootなしでSpringを長い間使用しなかったので、私は愚かなことを言いたくありません。
補足として、@Value
設定するフィールドが多い場合@ConfigurationProperties
は、引数が多すぎるコンストラクタが必要ないため、アノテーションを付けたクラスにフィールドを抽出する方が適切です。