0

Phoneオブジェクトのオブジェクトをモックする方法。

以下のコード、

public class Fortest {

  UserDao userdao = new UserDao();
  Phone name = new Phone();
  public String handleUser(User user) {

    String returncode="failed";
    //User usr = new User("bob");
    String username=user.getUsername();
    String pass=user.getPass();
    System.out.println("username and password : "+username+" : "+pass);

    Phone name = new Phone();
    String ph = name.getA();
    System.out.println("ph "+ph);

    if(ph.equalsIgnoreCase("test")){
      System.out.println("A "+ph);
      returncode="done";
    }
    System.out.println("returning "+returncode);

    return  returncode;
    //System.out.println("name "+name.toString());
    //System.out.println(name.getA());
  }
}

ありがとう

4

4 に答える 4

2

あなたはそうしない。モックのルールの1つは、エンティティや値オブジェクトをモックしないことです。このルールを破る必要がある場合は、おそらく設計上の欠陥があることを意味します。

をモックする必要がある場合newは、ファクトリをオブジェクトに渡してから、ファクトリをモックする必要があります。これの非常に一般的な例は、Dateオブジェクトをモックする必要がある場合です。これは、この他の質問で非常によく説明されています:Dateクラスのデフォルトコンストラクターをモックする方法(最初の回答を確認してください)。

ちなみに、電話のインスタンスを呼び出すとname...うーん、正しく見えません。

于 2012-09-05T09:50:55.903 に答える
2

まず、いくつかの仮定をします。 user.getUsername()user.getPass()副作用はありません。はSystem.out.printlnあなたにとって重要ではありません。

このようにして、クラスは次のようになります。

public class Fortest {
    Phone name = new Phone();

    public String handleUser(User user) {
        String ph = name.getA();

        if(ph.equalsIgnoreCase("test")){
            return "done";
        }

        return  "failed";

    } 
}

したがって、テストには2つの条件があります。phone.getA()「テスト」で「完了」を返すか、そうでない場合は「失敗」を返します。

だからセット" getA"を設定する方法。1つ確かなことは、テストから「名前」を設定できる必要があるということです。そのためには、それを「注入」する必要があります(他の多くの方法で実行できますが、注入が大好きです)。私はGuiceを使用し、多くの人がSpringを使用します。他のインジェクションフレームワークの1つを使用するものもあります。しかし、テストでは、ほとんどの人が手動注入を使用します。

public class Fortest {
    Phone name;
    Fortest(Phone name) {
        this.name = name;
    }

    public String handleUser(User user) {
        String ph = name.getA();

        if(ph.equalsIgnoreCase("test")){
            return "done";
        }

        return  "failed";

    } 
}


public class TestFortest {
   @Before
   public void before() {
          name = ; //... 
          subject = new Fortest(name);
   }
}

これで、テストはかなり簡単になります。

public void whenTestModeIsEnabledThenReturnDone() {
     setPhoneIntoTestMode();
     String actual = subject.handleUser(null);
     assertEquals(actual, "done");
}

public void whenTestModeIsDisabledThenReturnFailed() {
     setPhoneIntoLiveMode();
     String actual = subject.handleUser(null);
     assertEquals(actual, "failed");
}

setPhoneIntoTestMode/の実装はsetPhoneIntoLiveMode、その複雑さに依存しますPhone。何らかの方法(モック、スタブなど)で「ファッキング」するよりも複雑な場合。これはあなたが書いたコードの塊である可能性があり、Mocketoのようなツールを使用している可能性があります。

Phoneオブジェクトが単純で、 ""メソッドを持っている、または持つことができる場合はsetA、それを使用します。

後で必要になると確信していますuserdao。その時点で同じことが行われます。オブジェクトを注入してモック/セットアップします。

于 2012-09-05T11:35:00.880 に答える
0

EasyMockを使用すると、クラスのモック作成が非常に簡単になります。内部でcglibを使用して、クラスのモックを実行します。EasyMockは、インターフェースクラスの両方をモックできます(クラスモック)。ドキュメントを参照してください。

したがって、電話のモックを取得するには、createMock(Phone.class)を呼び出すだけです。

Phone phoneMock = createMock(Phone.class);

アウグストが述べたように、クラスのモックを利用することは本当に良いデザインではありません。より良い方法は、インターフェースに向けてプログラミングし、依存性注入フレームワークを使用することです。

于 2012-09-05T10:33:30.783 に答える
0

nameしたがって、フィールドにモックを挿入するには、次のいずれかのオプションを実行する必要があります(メソッドで作成されたインスタンスの代わりにuserdao、フィールドインスタンスを使用できると想定します。new Phone

  1. コード内でコンストラクターを直接呼び出さないでください。代わりに、セッターを介したフィールドインジェクションを使用してください。これにより、テストで2つのクラスのモックインスタンスを提供できるようになります。メソッドで新しいインスタンスを作成する必要がある場合は、モックできるファクトリの使用を検討してください。

  2. 2つのフィールドにデフォルトのスコープセッターメソッドを提供します。これらの方法は、テスト目的でのみ実施されます。

  3. Refectionを使用して、フィールドをモックインスタンスに設定します。これを行う簡単な方法は、SpringのReflectionTestUtilsを使用することです。

これらのいずれかが配置されたら、モックされたインスタンスを提供して(Mockitoを使用している可能性があります)、テストする動作を駆動できます。可能であればオプション1が最適であり、次にオプション3が最適です。ただし、オプション3の欠点は、テストがプライベートフィールドの名前に依存していることです。

それで...

Phone phone = Mockito.mock(Phone.class);
Mockito.when(phone.getA()).thenReturn("blah");
objectUnderTest.setPhone(phone);

objectUnderTest.handleUser(...);
于 2012-09-05T11:29:57.637 に答える