1

説明されているように、dart unittest フレームワークと含まれている Mock クラスを使用しました

ただし、モック呼び出しには依存関係があります。

..store.when(callsTo('isLocked')).thenReturn(false);

isLockedメソッドへの呼び出しは名前で呼び出されます。誰かがisLockedメソッドの名前を変更した場合、リファクタリング フレームワークは呼び出しの名前を変更しません。

リフレクション(鏡)が何かに役立つのではないかと思っていましたが、解決策が見つかりませんでした。

乾杯ピーター

4

2 に答える 2

1

原則として、特にこの問題があるため、(RESTful Web API などの外部リソースを利用しない限り) クラスをモックすることは避けようとしています。クラス A がクラス B の foo メソッドをモックアウトしても、クラス B が実際にその foo メソッドの名前を fooBar に変更した場合でも、テストはパスします。ただし、クラス A が実行時に B.foo を呼び出そうとすると、クラッシュします。したがって、ローカルで利用できるものをモックすることは避けています。

幸いなことに、Dart の状況は、他の動的言語よりも少し良くなっています。たとえば、別のクラスを実装するクラスを作成できます。したがって、FakeB が B を実装する場合、A をテストするときに使用できる関数を FakeB に追加できます。

当然のことながら、コードの callsTo('isLocked') が、実際には isReallyLocked に名前が変更された isLocked という名前のメソッドを実際に参照していることを、リファクタリング フレームワークが認識するのは少々面倒です。ただし、ミラー API を見ると正しい道を進んでいると思います。たとえば、callsTo(isLocked. name ) と記述できれば素晴らしいと思います。そうすれば、VM はモックに対してより多くのチェックを提供できます。

当然のことながら、本当の目的は、API が一致しない場合にテストを失敗させることです。私は mirrors API をいじってみました。

#import('dart:io');
#import("dart:mirrors");

void a() {
  print("a");
}

void main() {
  String thisFile = "file://${new Directory.current().path}/${new Options().script}";
  print(currentMirrorSystem().libraries[thisFile].functions['a'].simpleName);
}

このコードは引き続き "a" を文字列として使用しますが、"a" が関数として存在しない場合は失敗するという利点があります。ちょっと醜くてハッキーですが、探していた方向に向かっています。

あなたができるもう一つのことは次のようなものです:

when(callsTo('isLocked')).alwaysCall(isLocked)

この場合、モッキング システムは、呼び出し元と isLocked 関数の間の仲介者を演じているだけです。このアプローチには 2 つの欠点があります: a) おそらく isLocked の呼び出しを完全に回避しようとしていたと思われます。ただし、いくつかの利点があります。a) isLocked が呼び出されているという事実を記録できます。b) isLocked の名前が変更されている場合は機能しません。つまり、isLocked の名前を変更した人はこのコードを見て、できれば両方の場所を更新します。

別の「ブルートフォース」アプローチは次のとおりです。

void a() {
  print("a");
}

String makeSureItExists(obj, String name) {
  return obj != null ? name : "NoSuchMethod";   
}

void main() {
  print(makeSureItExists(a, "a"));
}

これにより、callsTo(makeSureItExists(login, "login")) のようなものを記述できます。

于 2012-09-12T21:15:30.740 に答える
0

さて、私が最終的に使用したメソッドは、メソッド名を持つ定数クラスです。そのようです:

class MethodNames{
  final String GET_ELEMENT = 'getElement';
  final String GET_CLASSES = 'get classes';
  final String SET_DISABLED = 'set:disabled';
  final String AS_INPUT = 'asInput';
  final String AS_BUTTON = 'asButton';
  final String SET_INNER_HTML = 'set:innerHTML';
  final String SET_VALUE = 'set:value';
...
  const MethodNames();
}

私は素晴らしくてシンプルであるという利点があります。私はそれを好む傾向があります。

乾杯ピーター

于 2012-11-20T11:22:47.310 に答える