2

JMockit で、実際のメソッドをトリガーする機能を維持しながら、クラス内にプライベート フィールドを挿入する方法を探しています。私はJMockitによって使用@Injectableおよび提供されています。@Testedしかし、その後どういうわけか、注入されたインスタンスは実際のメソッドを呼び出すことができません。

テスト例:

public class TestClass {
    public static class DoSomething {
        private Call callee;

        public void execute() {
            callee.call();
        }
    }

    public static class Call {
        public void call() {
            System.out.println("real");
        }
    }

    @Tested DoSomething doSomething;
    @Injectable Call call;

    // nothing happens
    @Test
    public void testRealCall() {
        doSomething.execute();
    }

    // invocation doesn't help either
    @Test
    public void testRealCallSecondTry() {
        new MockUp<Call>() {
            @Mock
            @SuppressWarnings("unused")
            public void call(Invocation inv) {
                inv.proceed();
            }
        };
        doSomething.execute();
    }

    // this works, but requires redundant methods
    @Test
    public void testRealCallThirdTry() {
        new MockUp<Call>() {
            @Mock
            @SuppressWarnings("unused")
            public void call() {
                System.out.println("real");
            }
        };
        doSomething.execute();
    }

    @Test
    public void testFakeCall() {
        new MockUp<Call>() {
            @Mock
            @SuppressWarnings("unused")
            public void call() {
                System.out.println("fake");
            }
        };
        doSomething.execute();
    }
}

ここでは、メッセージを出力する方法を提供するインスタンスをDoSomethingラップします。Call4 つのテスト ケースの理想的な出力は次のようになります。

real
real
real
fake

ただし、実際のシナリオでは、3 と 4 のみが機能し、次のように出力されます。

real
fake

これは、インスタンスが を使用して作成されたかどうかを示します@Injectable。古いメソッド本体をモック バージョンにコピー アンド ペーストしないと、元のメソッドを直接呼び出すことはできません。それは本当に厄介なようです。これの回避策はありますか?

4

2 に答える 2

2

私の理解では、 @Injectable を使用すると、空のモックが取得され、元のメソッドを呼び出すことができなくなります。

私が使用する回避策は、次のように「手動で」注入を行うことです。

public class TestClass {
  public static class DoSomething {
    private Call callee;

    public void execute() {
      callee.call();
    }
  }

  public static class Call {
    public void call() {
      System.out.println("real");
    }
  }

  @Tested DoSomething doSomething;
  //@Injectable Call call;

  // nothing happens
  @Test
  public void testRealCall() {
    Deencapsulation.setField(doSomething, "callee", new Call());
    doSomething.execute();
  }

  // invocation doesn't help either
  @Test
  public void testRealCallSecondTry() {
    new MockUp<Call>() {
      @Mock
      @SuppressWarnings("unused")
      public void call(Invocation inv) {
        inv.proceed();
      }
    };
    Deencapsulation.setField(doSomething, "callee", new Call());
    doSomething.execute();
  }

  // this works, but requires redundant methods
  @Test
  public void testRealCallThirdTry() {
    new MockUp<Call>() {
      @Mock
      @SuppressWarnings("unused")
      public void call() {
        System.out.println("real");
      }
    };
    Deencapsulation.setField(doSomething, "callee", new Call());
    doSomething.execute();
  }

  @Test
  public void testFakeCall() {
    new MockUp<Call>() {
      @Mock
      @SuppressWarnings("unused")
      public void call() {
        System.out.println("fake");
      }
    };
    Deencapsulation.setField(doSomething, "callee", new Call());
    doSomething.execute();
  }
}
于 2013-11-12T08:36:13.763 に答える