2

わかりました、奇妙な問題があります。

C# テスト プロジェクトで NUnit と Moq を使用しています。本当の問題は UserManager.AddUser() が適切に実行されていないことにあるため、モックオブジェクトは無視できると思います。

次のコードは、UserManager.AddUser() の開始時にブレークポイントに到達しないため、NullPointerException によりアサーションで失敗します。

[Test]
enter code here
public void AddUser_NoPassword_GeneratesPassword()
    {
        //assert
        var userRepositoryFake = new Mock<IUserRepository>();
        userRepositoryFake.Setup(x => x.GetUser(It.IsAny<string>(), It.IsAny<bool>())).Returns((User)null);
        userRepositoryFake.Setup(x => x.SaveUser(It.IsAny<User>())).Returns(new Mock<User>().Object);

        var userManager = new UserManager(userRepositoryStub.Object);
        var createUserViewModel = new CreateUserViewModel { Username = "username" };

        //act
        var validationErrors = userManager.AddUser(createUserViewModel);

        //assert
        Assert.IsNotNullOrEmpty(createUserViewModel.Password);
    }

ただし、このアサーションを追加すると:

        //assert
        Assert.IsEmpty(validationErrors); //new assertion
        Assert.IsNotNullOrEmpty(createUserViewModel.Password);

AddUser() のブレークポイントに到達し、テストは成功します。戻り値が何かに使用されない限り、テストは AddUser() をまったく実行しないようです。

4

1 に答える 1

5

私の推測では、AddUser次のように実装されています。

public IEnumerable<Error> AddUser(Model model)
{
    // Do some stuff
    if (foo)
    {
        yield return ...;
    }
    if (bar)
    {
        yield return ...;
    } 
    // More stuff
}

つまり、反復子ブロックを使用します。イテレータ ブロックは遅延実行されます。コードは、最初の要素が要求されたときにのみ実行を開始し、その要素が返されたときに「一時停止」します。

これはべき等クエリなどではないことを考えると、List<Error>追加して最後に返す内部を使用してメソッドを実装する方がはるかに理にかなっていることをお勧めします。そうすれば、メソッドは正確に 1 回実行されますが、戻り値は何度も繰り返されます。それが予想される実行モデルだと思います。

于 2013-04-26T15:11:40.280 に答える