3

オブジェクトを取り込んでデータベースに保存するメソッドがあります。しかし、オブジェクトを保存する前に、次のことを行います...

(疑似コード)

if (IsAuthenticated)
{
   foo.UserId = AuthenticatedUser.Id;
}
else
{
   foo.AnonEmail = "Jon@World-Domination";
   foo.AnonName = "Jon Skeet";
}

try
{
    _fooService.Save(foo);
}
catch
{
    // Some view, with error stuff now added to 
    return View(...); ViewData.ModelState.
}

// all good, redirect to the proper next view.
return RedirectToAction(...);

そのコードは正常に動作しますが、2 つの単体テストを成功させる方法がわかりません。a) ユーザーは有効なデータで認証されます b) ユーザーは有効なデータで認証されません。

何をすべきかわからない理由は、両方のシナリオが同じ RedirectToAction(..) ビュー オブジェクトを返すためです。だから私はそれをうまくテストできます..しかし、保存されたオブジェクトに認証されたユーザーIDまたは匿名情報が含まれているかどうかはわかりません。最初の単体テストで言いたいことのようです

  • 認証済みユーザーを moq アップする
  • 呼び出し方法
  • 結果が RedirectToActionView かどうかをテストします
  • 永続化された foo オブジェクトに moq されたユーザー ID が含まれているかどうかをテストします。

考え?

アップデート

一般的な提案は、fooService をモックすることです。私は現在 Dependency Injection と Moq を使用しています。ここでDIがどのように重要かはわかりませんが、???

4

6 に答える 6

3

オブジェクトをモックアップし、_fooServiceテストの一部として受け取るものをテストします。そうすれば、周囲のコードは変更されずに変更されず、何_fooServiceを受け取るかを確認することで、動作が期待どおりかどうかを確認できます。この場合、戻りオブジェクトは重要ではありません。

どのようにあなたを嘲笑します_fooServiceか? 独自の「テスト」バージョン (実際のバージョンと同じインターフェイスに準拠) を実装するか、モック フレームワークを使用することができます。どちらのアプローチを使用する場合でも、上記のコードは、特定の実装で構成する必要があります_fooService(通常は構築時に -これがどのように機能するかについての詳細は、依存性注入を参照してください)。

于 2009-04-07T13:13:58.900 に答える
1

1 つのメソッドで複数のアクティビティを実行しているため、オブジェクトをテストするのが難しい場合があります。

ここでの全体的なテーマはコントローラー ロジックです。

  1. ドメイン オブジェクトをユーザー情報で装飾する
  2. 更新ロジックを永続化する
  3. 成功/失敗に基づいてレンダリングする次のビューを決定する

別のオブジェクト (IUserDecoratorService) を抽出すると、コードは次のようになります。

userService.UpdateUserInformation(foo);

try
{
    _fooService.Save(foo);
}
catch
{
    // Some view, with error stuff now added to 
    return View(...); ViewData.ModelState.
}

// all good, redirect to the proper next view.
return RedirectToAction(...);

この方法は、2 つのサービスとの 2 つの単純な対話と、既にテストできるルーティングの決定であるため、簡単にテストできます。

あとは、新しいサービスのテストを作成するだけです。

[Test]
public void ShouldDecorateWithUserIdForAuthenticatedUser()
{
    {setup authenticated user}
    :
    service.UpdateUserInformation(foo);

    Assert.AreEqual(expectedId, foo.UserId);
    Assert.IsNull(foo.AnonEmail);
    Assert.IsNull(foo.AnonEName);

}

[Test]
public void ShouldSpoofTheAllKnowingSkeetIfAnonymousUser()
{
    {setup anonymous user}
    :
    service.UpdateUserInformation(foo);

    Assert.AreEqual(UnassignedId, foo.UserId);
    Assert.AreEqual("Jon@World-Domination", foo.AnonEmail);
    Assert.AreEqual("Jon Skeet", foo.AnonName);

}
于 2009-04-09T20:31:17.123 に答える
1

_fooService.Save(foo) をモックして、提供された foo を調べることができます。

于 2009-04-07T13:15:24.280 に答える
0

DI を使用して fooservice の正しい実装をオブジェクトに取得したいので、テスト時にこれを行うことができます。

(Moqを使用)

[TestMethod]
public void Jon_Skeet_Is_Saved_If_User_Not_Authenticated()
{
  bool jonWasSaved = false;
  var mockFooService = new Mock<IFooService>();
  mockFooService
       .Expect(x => x.Save(It.Is<Foo>(foo => foo.AnonName == "Jon Skeet")))
       .Callback(() => jonWasSaved = true;);

  FooManager instance = new FooManager(mockFooService.Object);
  Foo testFoo = new Foo();
  testFoo.UserId = 1; // this is not the authenticated id

  instance.baa(foo);

  Assert.IsTrue(jonWasSaved);
}

AuthetnicatedUser.Id をチェックするために使用するサービスのモック バージョンを渡すこともできます。

HTH

于 2009-04-08T11:48:27.773 に答える
0

オブジェクトへの参照がまだあります。単体テストの最後に、foo.AnonEmail または UserId の値をアサートできませんでしたか?

単体テストは外部ソースに触れるべきではありません (これは統合テストです)。そのため、そのルートに進む場合は、データソースをモックしてから、モックを介してテストする必要があります。

于 2009-04-07T13:15:28.353 に答える
0

テストで foo にアクセスできますか? クラスのフィールドだと思います。パブリックゲッターはありますか?そうでない場合は、Reflection を使用する必要があるかもしれません (asp.net で利用できると思いますが、あまり詳しくありません)。

于 2009-04-07T13:15:44.560 に答える