1

一部のクラス X が java.util.AbstractMap を拡張し、さらにオーバーロードを拡張するという問題が発生していequals(Object)ます。呼び出しorg.testng.Assert.assertEquals(X a, X b)は に解決されassertEquals(Map<?,?>, Map<?,?>)ます。「equals」メソッドを呼び出す代わりに、マップ エントリが比較されます。これにより、falseassertEquals(a, b)であっても合格になります。a.equals(b)

このコードは問題を示しています。

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import java.util.AbstractMap;
import java.util.Collections;
import java.util.Set;

import org.testng.annotations.Test;

public class AssertTest {
    static class X extends AbstractMap<String, Object> {
        private int i;

        public X(int i) {
        this.i = i;
        }

        @Override
        public Set<Entry<String, Object>> entrySet() {
        return Collections.EMPTY_SET;
        }

        @Override
        public boolean equals(Object o) {
        return o instanceof X && i == ((X)o).i;
        }

        @Override
        public int hashCode() {
        return i;
        }
    }

    @Test
    public void test() {
        X one = new X(1);
        X two = new X(2);
        assertEquals(one, two); // passes, should fail IMO
        assertTrue(one.equals(two)); // correctly fails
    }
}

この問題を回避する最善の方法は何ですか? 1 つの可能性は、X のインスタンスが一致することを確認するために を使用しないことを覚えておくことassertEqualsですが、これは非常にエラーが発生しやすいです。

もう 1 つの可能性は、単純に testng のローカル コピーを作成し、オーバーロードの名前を変更することです。これにより、継続的なメンテナンスの問題が発生します。

私が持っている他の唯一のアイデアは、testng.Assert に委譲するが、問題のあるオーバーロードの名前を「assertCollectionEquals」、「assertMapEquals」などに変更する、プロジェクト固有の Assert クラスを作成することです。

4

1 に答える 1

3

org.testng.Assert.assertEquals(X a, X b)お気づきのように、エントリセットを反復処理し、すべてのエントリが等しいことを確認するメソッドを呼び出しassertEquals(Map, Map)メソッドMap#equalsをバイパスします。

単純なキャストでは、そのメソッドの呼び出しを回避し、X#equals代わりにメソッドを使用します。

assertEquals((Object) one, (Object) two);

同じ結果を得るために、変数をオブジェクトとして宣言することもできます。

Object one = new X(1);
Object two = new X(2);
assertEquals(one, two);

それでもエラーが発生しやすいという意味で、それは実際には問題を解決しません。

assertEquals偶発的なエラーを回避するために、キャスト呼び出しなしで次の事実を使用して、考えられるいくつかの回避策があります (ここで疲れているため、ほとんど意味がない場合があります) x.entrySet()

  • Xクラスのすべてのテストファイルを解析するコードを書き、キャストが適切に配置されていることを確認する(単純ではありません)か、変数Xの左側でnoが宣言されていることを確認してください=
  • モックフレームワークを使用し、メソッドで X をモックし@BeforeGroups(グループを使用する場合)、そのイディオムに依存する各テストを同じグループに配置して、entrySet がテストに失敗した場合にモック X を使用するようにします (そして、他のメソッドは次のように機能します)。予想される)、または少なくともいくつかの警告をログに記録/出力します。entrySet機能しない同じ方法で使用する必要がある場合
  • モック フレームワークを使用してモックを作成TestNG#assertEquals(Map, Map)し、目的の動作を取得します。
  • そのイディオムを必要とするすべてのテスト クラスで、アドホックassertEquals(Map, Map)メソッドを作成します。すべての assertEquals メソッドの静的インポートがある場合は、他のシグネチャも再実装する必要があります :-(
  • これらすべてのテスト クラスに、assertEquals(Map, Map)メソッドを実装する BaseXTestClass を継承させる - 同じ警告
于 2013-01-23T20:58:04.547 に答える