4

JUnitで実装された2つの統合テストがあります。どちらのテストもリモート サーバーへの呼び出しを実行し、サーバー ターゲットは環境変数によって構成されます。

System.setProperty("property", "value1");

注意が必要なのは、これらのプロパティが 2 つのテストで異なる必要があることです。単体テストごとに環境変数を設定すると、機能しません。これは、使用しているミドルウェアが最初の呼び出しでプロパティ値をキャッシュし、それ以上評価しないためです (2 番目のテスト)。

解決策は、これらの単体テストを別々のプロセスで実行することだと思います。ここで同様の議論を見ましたが、JUnit4でこれを行うためのよりエレガントな方法があるでしょうか? この問題はかなり一般的です。または、別の構成で単体テストを実行する別の方法があるでしょうか?

アドバイスをよろしくお願いします。

4

5 に答える 5

3

JUnitをどのように実行しているかによって異なります。

IDE またはビルドから実行できるようにする場合は、カスタムを実装し、Runner注釈を使用してテスト ケースをマークしますRunWith(MyRunner.class)

Maven を使用していて、そこから定義に使用<forkMode>always</forkMode>するテストを実行できれば十分です。maven-surefire-plugin

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.11</version>
            <configuration>
                <systemProperties>
                    <systemProperty>
                        <name>panpwr.conf.dir</name>
                        <value>${basedir}/conf-test</value>
                    </systemProperty>
                </systemProperties>
                <forkMode>always</forkMode>

于 2012-09-03T10:20:16.853 に答える
2

テスト間でリセットできない状態を持つことは、悪い習慣と見なされます。簡単にテストできないコードはよくあることですが、解決策は簡単ではありません。

リフレクションを使用している場合でも、キャッシュされた値をリセットすることを検討します。正確に何をリセットする必要があるかは、ライブラリの内部表現によって異なります。

于 2012-09-03T10:14:26.137 に答える
1

レガシーコードの作業中にjunitテストを分離する必要があったため、すべてのJunitテストメソッドを個別の外部プロセスで開始できる小さなmavenプラグインJuteを開発しました。GitHubとmaven centralで公開しました。プラグインが適切かもしれませんあなたの質問に対する解決策、またプラグインは異なるJVMでそのようなテストを開始することを可能にします

于 2015-05-17T16:24:50.437 に答える
0

ProcessBuilder APIを使用すると、各プロセスを起動する直前に環境変数を変更できます。これを行う方法のコード スニペットを次に示します。

 @Test
 void testVariant1(){
      String [] commandArray = 
        {"java", "-cp", "your/class/path", "org.mydomain.myClass", ...};
      Map<String, String> envVarsForThisTest = new HashMap<String, String>();
      envVarsForThisTest.put("newProperty", "value1");
      List<String> staleVars = new List<String>();
      stateVars.add("oldProperty");
      File workingDir = new File("myDir"));
      Process p = runVariant(
                commandArray, envVarsForThisTest, staleVars, workingDir);
      Assert.assert(p.waitFor(), 0);
      checkAssertions(p.getOutputStream(), p.getErrorStream());
 }

 void checkAssertions(OutputStream output, InputStream errorStream){
      // where you'll check the return values against your expectations
 }

 void runVariant(String commandArray[], 
           Map<String, 
           String> newEnvironmentVariables, 
           List<String> environemntVariablesToRemove, 
           File workingDirectory){
      ProcessBuilder pb = new ProcessBuilder(commandArray);
      Map<String, String> env = pb.environment();
      for(Map.Entry<String, String> entry : newEnvironmentVariables){
           env.put(entry.key(), entry.value());
      }
      for(String staleVariable : environemntVariablesToRemove){
           env.remove(staleVariable);
      }
      pb.directory(workingDirectory);
      return pb.start();
 }
于 2012-09-03T11:29:17.210 に答える
-2

通常、単体テストはリモート サーバーなどの外部リソースに依存すべきではありません。そうしないと、ユニットをテストするのではなく、ユニットが依存するリソースの可用性と正確性をテストすることになります。

では、そのようなユニットをどのようにテストできますか?

通常、これはモック オブジェクトで行います。外部リソースへの呼び出しをオブジェクトにカプセル化し、このオブジェクトをテストするユニットに渡します (依存性注入と呼ばれます)。単体テストでは、実際のサーバー抽象化オブジェクトを渡しません。代わりに、同じインターフェイスを実装するか、サーバー抽象化クラスを拡張するモック オブジェクトを渡します。モック オブジェクトは実際にはサーバーにクエリを実行しません。代わりに、サーバーが返す値をすぐに返します。

これには、コードのリファクタリングが必要になる可能性があります。ただし、外部リソースに依存せずに単体テストを機能させることができます。また、テストが大幅に高速化され、テスト スイートの全体的な実行時間が短縮されます。これにより、単体テストをより頻繁に実行できます

于 2012-09-03T10:26:17.520 に答える