4

(getter関数を介して)読み取り専用にすることを目的としたプライベートフィールドを含むデータモデルクラスがあります。これらのフィールドは、データベースのコンテンツを使用して、通常の操作中にJPA永続性プロバイダー(eclipselink)によって設定されます。単体テストでは、永続層のモックアップからの偽の値に設定したいと思います。どうやってやるの?とにかく、eclipselinkはこれらの値をどのように設定しますか?

簡略化した例:

@Entity
class MyEntity
{
    @Id
    private Integer _ix;

    public Integer ixGet()
    {
        return this._ix;
    }
}
4

8 に答える 8

9

エンティティ自体をモックして、ゲッターの独自の実装を提供できますか?

模擬永続層に匿名の拡張機能を作成できます。

MyEntity x = new MyEntity() {
    public Integer ixGet() { return new Integer(88); }
};
于 2009-08-20T13:28:59.220 に答える
8

ReflectionAPIを使用する必要があります。Class.getField()を使用してフィールドを取得し、そのフィールドでsetAccessable(true)を呼び出して、プライベートであっても書き込みができるようにします。最後に、set()を呼び出して新しい値を書き込みます。

例えば:

public class A {
    private int i;
}

プライベートであっても、フィールド'i'を3に設定するとします。

void forceSetInt(Object o, String fieldName, int value) {
    Class<?> clazz = o.getClass();
    Field field = clazz.getDeclaredField(fieldName);
    field.setAccessible(true);
    field.set(o, value);
}

処理する必要のある例外がいくつかあります。

于 2009-08-20T13:34:53.830 に答える
4

Mockitoなどのテストライブラリを使用して、読み取りおよび書き込みモードでオブジェクトの内部状態にアクセスできます。たとえば、Mockitoを使用する場合:

//read
Integer i = Whitebox.getInternalState(myEntity,"_ix")
//Write 
Whitebox.setInternalState(myEntity,"_ix", 123) 
于 2016-05-08T15:29:36.207 に答える
3

powermockのようなモックフレームワークを使用して、カプセル化をバイパスできます。powermockではWhitebox.setInternalState(..)、プライベートメンバーを設定するために使用します。

より侵襲性の低い方法は、ゲッター法を模倣することです。これが実行可能かどうかは、他に何が内部状態に依存するかに依存しますが、それで十分であれば、よりクリーンなソリューションです。

于 2009-08-20T13:35:06.420 に答える
2

別のオプションは、物事を公開するのが本当に嫌いな場合は、テスト用のサブクラスを作成し、そこにパブリックアクセスを提供することです。

いくつかのオプションがあります。

  • エンティティを置き換えるスタブを作成します(最初にインターフェイスを抽出します)
  • リフレクションを使用する
  • テスト用のパブリックセッターを追加します
  • テストをパッケージ内に保持し、デフォルトのスコープを使用します

便利なテクニックの束については、MichaelFeatherの本「WorkingEffectivelyWithLegacyCode」をご覧ください。

于 2009-08-20T13:32:53.257 に答える
2

私が過去に使用したいくつかの方法:

  • _ixを保護し、セッターを実装するサブクラスを作成します
  • _ixの値をパラメーターとして取るコンストラクターを作成します
  • リフレクションを使用する
于 2009-08-20T13:30:13.680 に答える
2

読み取り専用変数のパラメーターを使用してコンストラクターを追加できます。デフォルト(ゼロパラメーター)コンストラクターを追加することを忘れないでください。

@Entity
class MyEntity
{
    @Id
    private Integer _ix;

    public MyEntity(Integer ix) {
        _ix = ix;
    }

    public MyEntity() {
        /*
         * Default constructor
         */
    }

    public Integer ixGet()
    {
        return this._ix;
    }
}
于 2009-08-20T13:40:22.577 に答える
1

コンストラクターは私が思う最良の方法です。このエンティティが本当に読み取り専用である必要がある場合(本番コードで新しいインスタンスを作成することはまったく許可されていません)、パッケージアクセスを使用してコンストラクターを作成し、テスト内でのみ使用できます。また、デフォルトのコンストラクターをプライベートまたはパッケージアクセスで作成した場合でも、永続性プロバイダーはそのようなエンティティーを操作できる可能性がありますが、確かではありません。eclipselinkのドキュメントを確認してください。

于 2009-08-20T14:49:13.930 に答える