2016-09-21 11 views
0

私のJavaクラスPartitionMapperには、PartitionMapperTestというテストを書く必要があります。このクラスには、@Injectアノテーションを持つプライベートフィールドがありますが、それにはノンパラメコンストラクタのみがあります。テスト中に@Injectを持つプライベートフィールドを注入しますか?

テストのために、テストの前にpartitionMapperを作成して、そのプライベートフィールドに値を注入したいと思います。次に、テスターはマッパーのメソッドmapPartitionsをテストし、値をアサートします。しかし、これらの値をpartitionMapperに注入する方法はわかりません。

PartitionMapper.java

@Named 
public class PartitionMapper implements javax.batch.api.partition.PartitionMapper { 

    @Inject 
    private JobContext jobContext; 

    @Inject 
    @BatchProperty 
    private String fetchSize; 

    @Inject 
    @BatchProperty 
    private String rowsPerPartition; 

    // other batch properties ... 

    @PersistenceUnit(unitName = "h2") 
    private EntityManagerFactory emf; 

    @Override 
    public PartitionPlan mapPartitions() throws Exception { 
     // ... 
    } 
} 

PartitionMapperTest.java

public class PartitionMapperTest { 

    private PartitionMapper partitionMapper; 

    @Before 
    public void setUp() { 
     // Prepare JobContext, batch properties to inject ... 

     // Instantiation 
     partitionMapper = new PartitionMapper(); 

     // TODO How to inject these objects into partitionMapper? 
    } 

    @Test 
    public void testMapPartitions() throws Exception { 
     PartitionPlan partitionPlan = partitionMapper.mapPartitions(); 
     for (Properties p : partitionPlan.getPartitionProperties()) { 
      // Assertions here ... 
     } 
    } 

    // ... 
} 

私は実際に私のGitHubで見ることができMockitoとPowerMockに基づいて実PartitionMapperTestを実装しました。問題は非常に多くの前提があるため、ユーザーの理解のために非常に貧弱なコードにつながるということです。私はそれをリファクタリングするための別のソリューションを探しています。

答えて

2

no argsコンストラクタしか持たない理由はありますか?

フィールド注入の代わりにコンストラクタ注入を使用することをお勧めします。それはあなたの問題を解決するだろう。

の代わりに、たとえば:あなたはあなたの注入ポイントを定義する場合

public class Foo { 
    private Bar bar; 

    public Foo(@Inject Bar bar) { 
     this.bar = bar; 
    } 
} 

あなたはクリーンなAPIを持ってこのようにして、あなたのクラスは、非CDI環境で使用することができます。

public class Foo { 
    @Inject 
    private Bar bar; 
} 

これを行います(単体テストのように)。

"コンストラクタ注入VSフィールド注入"については、多くのリソースがあります。 https://stackoverflow.com/a/19382081/4864870。ユニットテストのフィールドを模擬することができるようにする

+0

あなたは答えは良いアイデアです。私はおそらくそれを選ぶだろう。しかし、私はCDIが値をプライベートフィールドにどのように注入するのか知りたいのですか?つまり、セッターはいないのですが、達成方法は?私が同じ仕組みを適用しても、私は達成することができますか? (自分で注入する) –

+0

私は誰もAPI内でこの内部クラスをインスタンス化しないようにしたいので、引数なしのコンストラクタしか持たないでください。しかし、彼らはまだ実際にそれを行うことができます:/ –

+1

フィールド注入は私が知る限り、反射を必要とします。私はそれが次のように行われると仮定します: 'Field field = Example.class.getDeclaredField(" fieldName "); field.setAccessible(true); field.set(インスタンス、値); 'あなたのクラスが内部的にのみ使用されるようにしたい場合は、コンストラクタパッケージをプライベートにすることができます。それは100%解決策ではありませんが、何もありません。これを行うと、あなたのテストが同じパッケージになっていることを確認してください;) –

0

使っ保護フィールドの代わりに、民間:

@Named 
public class PartitionMapper implements javax.batch.api.partition.PartitionMapper { 

    @Inject 
    JobContext jobContext; 

    @Inject 
    @BatchProperty 
    String fetchSize; 

    @Inject 
    @BatchProperty 
    String rowsPerPartition; 

    // other batch properties ... 

    @PersistenceUnit(unitName = "h2") 
    EntityManagerFactory emf; 

    @Override 
    public PartitionPlan mapPartitions() throws Exception { 
     // ... 
    } 
} 
+0

実際には、私はmockitoとpowermockを使って私的なフィールドでそれらを嘲笑することができます。私のテストに合うようにソースコードを変更したくありません。そして私はあなたが私の質問を誤解したと思う。私はあまりにも多くの擬似を以前行ったので、今私は黙っていないアプローチを注入に切り替えるしたいと思います。どのようにそれを達成するための任意のアイデア? –

関連する問題