1

ゲームの改造中に問題が発生しました。メソッド自体を編集せずに、メソッドが返すものを変更する必要がありました。power-mock でこれを試してみましたが、役に立ちませんでした。power-mock やその他のバイトコード操作ライブラリ、さらには標準ライブラリでこれを行う方法を知っている人はいますか? ライセンスが私の目的に使用することを許可している限り、私はどんなライブラリも喜んで使用します。

すべてのオブジェクトで、静的メソッドの戻り値と非静的メソッドの戻り値を編集できるようにしたいと考えています。

これが私がpower-mockで試したことです

import org.powermock.api.easymock.PowerMock;

import static org.easymock.EasyMock.expect;

public class BeanTest
{
   public static void main(String[] args) throws Exception
   {
      Bean beanMock = PowerMock.createMock(Bean.class);
      expect(beanMock.convert("world")).andReturn("WORLD");
      System.out.println(beanMock.convert("world"));
   }
}

public class Bean
{
   protected String convert(String name) 
   {
      throw new UnsupportedOperationException("not implemented yet");
   }
}
4

2 に答える 2

3

Java では、戻り値の型はメソッド シグネチャの一部ではないため、好きなように処理できます。

これを透過的に実現するには、次の 2 つの方法があります。

  1. メソッドの呼び出し元であるこのオブジェクトの注入を制御できる場合は、Java 動的プロキシを使用します。
  2. AspectJ アスペクトを使用してアドバイスを回避すると、制御できないコード (サードパーティ ライブラリ) を操作できます。コンパイル時ウィービングまたはロード時ウィービングによる AspectJ の使用

編集:

Java 動的プロキシ (インターフェイスの場合) または CGlib (クラスの場合) を使用すると、インターフェイスを使用して、呼び出しと交差できるプロキシへのポイントを指定し、それを使用して何かを実行し、実際の実装に委任できます。それを達成するには、依存性注入を制御する必要があります。ここにいい説明があります。

例:

SomeInterface t = (SomeInterface) Proxy.newProxyInstance(SomeInterface.class.getClassLoader(),
                       new Class<?>[] {SomeInterface.class},
                       new TestInvocationHandler(new TestImpl())); 

機能: TestInvocationHandler は InvocationHandler インターフェースを拡張します。TestImpl は SomeInterface を実装するクラスです。SomeInterface からメソッドを呼び出すと、最終的に TestInvocationHandler になります。InvocationHandler には、次のような呼び出しメソッドが 1 つあります。

public Object invoke(Object proxy, Method method, Object[] args);
  • プロキシ - オブジェクトへの参照

  • method - 呼び出されるメソッド

  • args - メソッドの引数

AspectJ を使用すると、たとえばアラウンド アドバイスで何をラップするかをポイントカットで指定できます。AspectJ の利点は、明示的なプログラミングなしで、既にコンパイルされたコードまたは独自のコードを操作できることです。

例:

@Aspect
public class MyAspect {

    @Around("execution(* org.example.yourMethod(..))")
    public Object doNothing(ProceedingJoinPoint pjp) {

        // You can call the method or ignore the call and do your logic
        return pjp.proceed();
    }

 }

このhttp://www.hubberspot.com/2012/12/how-to-implement-around-advice-using_12.htmlは、Spring で AspectJ を使用する方法の良い例です。多分それは出発点としてあなたを助けることができます.

CGlib で説明するのはかなり難しいので、Java Dynamic Proxies で説明します。あなたの場合

 // I suppose Bean implements IBean interface
 IBean beanMock =  (IBean) Proxy.newProxyInstance (
                        IBean.getClass().getClassLoader(),
                        new Class[] { IBean.class },
                        new InvocationHandler() {
                            public Object invoke(Object proxy, Method method, 
                              Object[] args) throws Throwable {
                                if(method.getName().equals("convert")) {
                                    if(args[0].toString().equals("world")) {
                                        return "WORLD"
                                    }
                                } else {
                                    // Implement default case
                                }
                            }
                        });

 System.out.println(beanMock.convert("world"));
于 2013-03-19T22:27:15.437 に答える
0

あなたはかなり近かった。PowerMockのEasyMockフレーバーを使用しているようです。私はMockitoのフレーバーに精通しているので、あなたが試みていたことに基づいて合格する簡単な単体テストをコーディングしました:

import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
public class BeanTest {
    @Test
    public void testConvert() throws Exception {
        String worldLower = "world";
        String worldUpper = "WORLD";
        Bean beanMock = mock(Bean.class);
        when(beanMock.convert(worldLower)).thenReturn(worldUpper);
        assertEquals(worldUpper, beanMock.convert(worldLower));
    }
}

私が行った唯一の追加の変更はBean、 とBeanTestを別のクラス ファイルに配置することでした。

于 2013-03-20T12:22:47.590 に答える