2

Eclipse 内の Java アプリケーションの JUnit テストに EasyMock を使用しています。以下のようなコードを使用すると、奇妙な動作が見つかりました: 完全なテスト スイート (Eclipse プロジェクト -> Run as -> JUnit) を実行すると、1 つのテスト ケースが再現可能に失敗します。ただし、スタンドアロンで実行すると問題なく動作します。

インターフェース:

package de.zefiro.java.easymockexception;

public interface Fruit {
    public String fall();
}

テストクラス:

package de.zefiro.java.easymockexception;

import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertTrue;

import org.junit.BeforeClass;
import org.junit.Test;

public class Newton {
    private static final Fruit APPLE = createNiceMock(Fruit.class);

    @BeforeClass
    public static void SetUpClass() {
        expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
        replay(APPLE);
    }

    @Test
    public void testGravity() {
        String target = APPLE.fall();
        assertTrue("Missed", target.contains("HEAD"));
    }
}

テスト スイート:

package de.zefiro.java.easymockexception;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(value = Suite.class)
@SuiteClasses( { Newton.class } )
public class ScienceTests { }

Eclipse プロジェクトですべてのテストを実行すると (つまり、Newton を直接呼び出す ScienceTest と Newton の両方を呼び出す)、上記の小さな例でこの例外が発生しました。

java.lang.IllegalStateException: no last call on a mock available
at org.easymock.Easymock.getControlForLastCall(EasyMock.java:175)

ここに同様の質問がありますが、無関係のようです。

実際のテスト コード (より大きなクラスですが、主要なアクターは簡素化された例と同じです) では、次の例外が発生します。

java.lang.IllegalStateException: void method cannot return a value
at org.easymock.internal.MocksControl.andReturn(MocksControl.java:101)

GoogleでもここStackOverflowでも答えが見つかりませんでしたが、今自分自身を見つけたので、あなた自身の質問に答えるという精神で、私の発見を以下に投稿します. この特定のケースでは役に立ちませんでしたが、私が見つけたこの投稿も言及する価値があります: EasyMock Cause-Effect Exception Mapping

4

1 に答える 1

0

APPLE を初期化する行と SetUpClass() 内にブレークポイントを設定すると、APPLE は 1 回だけ呼び出され、SetUpClass は 2 回呼び出されることに気付きました。これは、Newton への最初の参照がクラスを作成し、静的初期化子を実行するという事実によるものですが、JUnit はテストの実行ごとに @BeforeClass を呼び出します。この場合、テストは 2 回実行されます。1 回は通常の呼び出しとして、もう 1 回はテスト スイートの一部として実行されます。

ロジックを変更したくなかった (つまり、静的を使用しない) 代わりに、静的 @BeforeClass を静的初期化ブロックに変更しました。

public class Newton {

    [...]

    static {
        expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
        replay(APPLE);
    }

    // no @BeforeClass needed anymore

    [...]
}

これにより、上記の単純化されたテストと実際のテスト コーディングの両方で問題が解決されました。

異なる例外メッセージをトリガーした違いが何であるかはわかりませんでしたが、結果は同じでした. new は1回だけ呼び出され、 @BeforeClass は複数回呼び出され、2回目の実行で失敗しました. 修正は両方で機能しました。

于 2012-04-10T17:08:09.137 に答える