1

以下は、ユーザーが提供したファイルがホームディレクトリの下にあるかどうかをチェックする単純なJavaクラスファイルです。ファイルがホームディレクトリの下にない場合は、例外がスローされます。

public class A {
  public static void main(String args[]) {
     if (new A().processArgs(args[0]) {
        throw Exception("Not under home directory");
     }
  }

  // A simple method to check if the file is at home directory
  private boolean processArgs(String s) {
    File f = new File(s);
    String userHome = System.getProperty("user.home");
    if (s.startsWith(userHome) && f.exists() && additionalLogic())
      return true;  
    else
      return false;
  }
  // Additional business Logic
  private boolean additionalBusinessLogic() {
    // Do wonderful things.
  }
}

Javaクラスをテストするための簡単なJunitテストケースを作成したいと思います。テストする主な関心事は、追加のビジネスロジックメソッドです。ディレクトリがユーザーのホームディレクトリの下にある必要があるチェックをバイパスする方法はありますか?

メインクラスにロジックを追加して、JUnitクラスを認識させるのは苦手です。これを行うためのより良い方法はありますか?

4

6 に答える 6

3

fabのソリューションには何の問題もありませんが、私は別のソリューションを作成することにしました。

public class Main {
    public static void main(String args[]) {
        // TODO: Should check args length
        Validator validator = new Validator();
        validator.validateArgs(args[0]);
    }
}

public interface Configuration {
    public String getHomeDirectory();
}

public class DefaultConfiguration implements Configuration {
    public String getHomeDirectory() {
        String home = System.getProperty("user.home");
        if (home == null) {
            throw new RuntimeException("User home directory is not set!");
        }
        return home;
    }
}

public class Validator {
  private Configuration configuration;

  public Validator() {
     this(new DefaultConfiguration());
  }

  public Validator(Configuration configuration) {
     this.configuration = configuration;
  }

  // A simple method to check if the file is at home directory
  public void validateArgs(String s) {
    File f = new File(s);
    if (!s.startsWith(configuration.getHomeDirectory()) || !f.exists() || !additionalBusinessLogic())
      throw new RuntimeException("Not under home directory!");
  }

  // Additional business Logic
  private boolean additionalBusinessLogic() {
     // TODO...
     return true;
  }
}

public class ValidatorTest {
  @Test
  public void validateValidArgsTest() {
     final String homeDirectory = ".."; // TODO
     String existingFile = homeDirectory + ".."; // TODO
     new Validator(new Configuration() {
       public String getHomeDirectory() {
          return homeDirectory;
       }
     }).validateArgs(existingFile);
  }

  @Test(expected = RuntimeException.class)
  public void validateInvalidArgsTest() {
     String existingFile = ".."; // TODO
     new Validator(new Configuration() {
       public String getHomeDirectory() {
          return "-INVALID PATH-";
       }
     }).validateArgs(existingFile);
  }
}
于 2013-02-13T21:52:27.207 に答える
2

テストをよりテストしやすくするために、クラスにテストを認識させる必要はありません。追加のロジックをi/oのものから切り離すだけで、より良い設計になります。

public class A {
  private WonderfulThingsDoer wonderfulService;

  public void main(String args[]) {
     wonderfulService = new WonderfulThingsDoer();
     if (processArgs(args[0]) {
        throw Exception("Not under home directory");
     }
  }

  // A simple method to check if the file is at home directory
  private boolean processArgs(String s) {
    File f = new File(s);
    String userHome = System.getProperty("user.home");
    if (s.startsWith(userHome) && f.exists() && additionalBusinessLogic())
      return true;  
    else
      return false;
  }
  // Additional business Logic
  private boolean additionalBusinessLogic() {
    return wonderfulService.doWonderfulThings();
  }
}

public class WonderfulThingsDoer {
  public boolean doWonderfulThings() {
    // Do wonderful things.
    return true;
  }
}

Voilá、テスト可能なユニットを抽出しました。

于 2013-02-13T21:24:07.147 に答える
1

「user.home」をハードコーディングしないでください

テストディレクトリを指すように、ユニットコードで変更するフィールドホームを作成します。

public class A {

      private static String homeDir;
      protected static void setHomeDir(String home) {
        this.homeDir = home;
      }    

      public static void main(String args[]) {
         if (homeDir == null) {
              homeDir = System.getProperty("user.home");
         }
         A a = new A();
         if (a.processArgs(args[0]) {
            throw new InvalidArgumentException("Not under home directory");
         }
      }

      // A simple method to check if the file is at home directory
      protected boolean processArgs(String s) {
        File f = new File(s);

        if (s.startsWith(A.homeDir) && f.exists() && additionalLogic())
          return true;  
        else
          return false;
      }
      // Additional business Logic
      private boolean additionalBusinessLogic() {
        // Do wonderful things.
      }
    }

ユニットテストで、homeDirをテストディレクトリに設定します

public void testMainHomeExisting() {
    A a = new A;
    String home = "./testdata/";
    A.setHomeDir(home);
    String[] args = new String[]{home}; // hope this compiles otherwise fix it
    // no assert needed here, if test fails, an Exception is thrown
    A.main(args);
}

現在、存在しない家のテストケース

public void testMainHomeNotExisting() {
    A a = new A;
    String home = "./notExistingFooBarFooFoo/";
    A.setHomeDir(home);
    String[] args = new String[]{home}; // hope this compiles otherwise fix it
    // no assert needed here, if test fails, an Exception is thrown
    try {
       A.main(args);
       // if code works the next line should not be reached:
       fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException ex) {
       // as expected got IllegalArgumentException
    }
}
于 2013-02-13T22:05:51.310 に答える
0

TestコアビジネスメソッドadditionalBusinessLogicのみを作成します。を呼び出す必要はありませんmain

于 2013-02-13T21:18:59.700 に答える
0

電話をかける理由はありませんmain

単体テストを作成するときは、外部メソッドにあまり依存せずに呼び出すことができるようにモジュール化する必要があります。呼び出しできないものは、EasyMock、PowerMock、Mockitoなどを使用モックできます。

于 2013-02-13T21:19:03.010 に答える
0

テストしたい方法を変更します...

  1. アクセス修飾子を削除します
  2. Fileロジックを実行できるようにするために必要な変数を渡します

boolean additionalBusinessLogic(File f)

これにより、同じパッケージ内のテストクラスがメソッドを呼び出すことができます。プライベートのままにすると、他のクラスはそれを呼び出すことができなくなります。

テストしたいメソッドを呼び出すことができれば、テストクラスは簡単です...

public class MyClassTest {
    @Test
    public void additionalBusinessLogic_shouldFoo_whenSomeCondition() {
        // setup
        A a = new A();
        File mockFile = mock(File.class);
        // other setup stuff

        // execute
        boolean result = a.additionalBusinessLogic(mockFile);

        // assert
        // verify whatever you need to
    }
}

優れたモックフレームワークとして、Mockitoをお勧めします。

于 2013-02-13T21:28:52.260 に答える