2

JSch を使用して SSH 接続を作成する次のコードを検討してください。

public class DoSsh {
  private static final int DEFAULT_PORT = 22;

  public DoSsh(String user, String pass) {
    JSch jsch = new JSch();
    Session sess = jsch.getSession(user, pass, DEFAULT_PORT);
    ...

そして、JMockit を使用する次のテスト コード:

@Test
public void testDoShs() {
  // Change the default port
  Deencapsulation.setField(DoSsh.class, "DEFAULT_PORT", 2222);
  DoSsh ssh = new DoSsh("me","mypass");
  ...

ここでの目標は、テスト中に SSH 接続で代替ポート (この場合は 2222) を使用してインメモリ SSH サーバー (Apache MIRA) に接続することです。

これをデバッグすると、'DEFAULT_PORT' の値が実際に変更されていることがわかります (JMockit に感謝します :-) 問題は、コンパイラが既に 'jsch.getSession' への呼び出しを最適化し、元の値をハードコーディングしていることです。その中に22。したがって、デバッガーでその呼び出しにステップインすると、渡される値が 2222 であっても、呼び出し内の値は 22 になります。

私の質問は、誰かが DEFAULT_PORT を非最終にすることを伴わないこれを解決する方法を提案できますか?

4

1 に答える 1

2

私自身の答えを見つけました。「jsch.getSession」への呼び出しをモックアウトしますが、その後、目的のポート番号を使用して、モック内から実際のバージョンを呼び出します。これは基本的に AOP アプローチです。カプセル化解除は使用されません。コードは次のとおりです。

@MockClass(realClass = JSch.class)
public static class MockedJSch {
    public JSch it;
    @Mock(reentrant = true)
    public Session getSession(final String user, final String pass, final int port) throws JSchException {
        return it.getSession(user, pass, TESTING_PORT);
    }
}

@BeforeMethod
public void beforeMethod() {
  Mockit.setUpMocks(MockedJSch.class);
}

ここで注意すべき重要な点が 2 つあります。

  1. モックされたメソッドは「再入可能」としてマークされます。
  2. モックには、「実際の」メソッドを呼び出すために使用される「it」と呼ばれるパブリック インスタンス メンバーがあります。そのインスタンス メンバーは、このメソッドが呼び出されるインスタンスを参照するために JMockit の内部のどこかで初期化され、その参照はメソッドの「実際の」バージョンにアクセスできます。
于 2012-12-20T22:57:59.947 に答える