2017-11-15 15 views
2

私はネットコアWEBAPIコントローラのアクションをテストするには、以下のxUnitテストを書く:.Net Coreのコントローラをテストすると常にfalseが返されますか?

AccountController

namespace VistaBest.Api.Controllers 
{ 
    public class AccountController : BaseController 
    { 
     private readonly IUsersBusinessObject _usersBusinessObject; 
     public AccountController(IUsersBusinessObject usersBusinessObject) 
     { 
      _usersBusinessObject = usersBusinessObject; 
     } 

     [HttpPost] 
     public IActionResult ValidateUser(LoginModel model) 
     { 
      if(!ModelState.IsValid) return BadRequest(ModelState); 
      return Ok(_usersBusinessObject.ValidateUser(model.Username, model.Password.ToMd5Hash())); 
     } 
    } 
} 

IUsersBusinessObject

namespace VistaBest.Data.BusinessObjects 
{ 
    public interface IUsersBusinessObject 
    { 
     bool ValidateUser(string username, string password); 
     UserModel SelectByUsername(string username); 
    } 

    public class UsersBusinessObject : BaseBusinessObject, IUsersBusinessObject 
    { 
     public UsersBusinessObject(IDbConnection connection) : base(connection) 
     { 

     } 

     private const string TableName = "Users"; 

     public bool ValidateUser(string username, string password) 
     { 
      var query = $"SELECT COUNT(*) FROM [{TableName}] WHERE UserName = @username and Password = @password"; 
      return DbConnection.QueryFirst<int>(query, new { username, password }) == 1; 
     } 
} 

ご覧のとおり私はusersBusinessObjectMockはretする必要があります骨壷true

usersBusinessObjectMock 
    .Setup(service => service.ValidateUser(username, password)) 
    .Returns(() => true); 

しかしvar result = okObjectResult.Value as bool?;は常にfalse

何が問題になっていますでしょうか?このエラーを見つけるのは本当に難しいですと、10分のようなあなたのコードを読んだ後

Test Error Screen Shot

+0

値をブール値にキャストするとどうなりますか?つまり、 'var result =(bool)okObjectResult.Value;' – Nkosi

+0

@Nkosi:結果は常にfalseです。メインポストの画像のwatchセクションを参照してください。 –

+0

私たちは間違ったティng。モックが正しく構成されていないため、期待どおりに動作しませんでした。私の答えをチェックしてください。 – Nkosi

答えて

1

コントローラは

_usersBusinessObject.ValidateUser(model.Username, model.Password.ToMd5Hash()) 
を呼んでいるが、パスワードで呼び出されて ToMd5Hash()に注意してください。

ます。ただし、セットアップのようなモックを...

usersBusinessObjectMock 
    .Setup(service => service.ValidateUser(username, password)) 
    .Returns(() => true); 

は、問題を参照してください?

疑似パスワードはハッシュパスワードではなく未処理パスワードを要求しているため、ハッシュパスワードを渡したときにはtrueが返されません。この結果、モックは常にfalseを返すため、アクションのオブジェクト結果は常にfalseを返します。その方法はスクリーンに隠されていたので、私はそれを以前に気付かなかった。

だから、テスト対象のメソッドに一致するようにハッシュされたパスワードを期待する模擬は

あなたのいずれかのセットアップ、ToMd5Hash()は、いくつかのカスタム拡張メソッドであると仮定すると...

usersBusinessObjectMock 
    .Setup(service => service.ValidateUser(username, password.ToMd5Hash())) 
    .Returns(() => true); 

またはモックの期待を緩めIt.IsAny<>()メソッドを使用して...

usersBusinessObjectMock 
    .Setup(service => service.ValidateUser(It.IsAny<string>(), It.IsAny<string>())) 
    .Returns(() => true); 

はそうつまりあなたはモックに渡す値かは重要ではありません、それは常にtrue

を返します。
+0

すばらしい、ありがとう –

6

。あなたはすべての権利...

 var okObjectResult = Assert.IsType<OkObjectResult>(actionResult); 
     var result = okObjectResult.Value as bool?; 
     Assert.True(result); 

しかし、ここでは、エラーがある...

varは危険ですやった... あなたの変数okObjectResultはタイプOkObjectResultからではありません...あなたのアサートは決してありません理由です真... あなたはこれがうまくいくと、私はあなたのコード内のいくつかの小さなリファクタリングを行う

Assert.IsType<OkObjectResult>(actionResult); 
var okObjectResult = (OkObjectResult) actionResult; 
+1

[Assert.IsType(T)](http://www.nudoq.org/#!/Packages/xunit.extensions/xunit.extensions/Assertions/M/IsType(T))は、提供されたオブジェクトを提供します。 – Nkosi

+0

私はあなたの書き込みのように自分のコードを変更し、何も変わらず、okObjectResultの値は常にfalseです! –

3

を入力するmean'tイムは確か。コントローラは、私は問題はあなたが正しくモックを設定していないことであることに気づい検証メソッドを呼び出す方法を再確認した後

namespace VistaBest.XUnitTest.Api.Test 
{ 
    public class Account_UnitTest 
    { 
    private readonly Mock<IUsersBusinessObject> _usersBusinessObjectMock; 
    private readonly AccountController _accountController; 
    public Account_UnitTest() 
    { 
     _usersBusinessObjectMock = new Mock<IUsersBusinessObject>(); 
     _accountController = new AccountController(_usersBusinessObjectMock.Object); 
    } 

    [Fact] 
    public void ValidateUserTest() 
    { 
     var model = new LoginModel 
     { 
      Username = "admin", 
      Password = "admin" 
     }; 

     _usersBusinessObjectMock.Setup(service => service.ValidateUser(model.Username, model.Password)).Returns(() => true); 

     var actual = _accountController.ValidateUser(model) as OkObjectResult; 

     actual.Value.ShouldBeEquivalentTo(true); 
     // or Assert.True(actual.Value); 
    } 
    } 
} 
+0

私はあなたの書き込みのように私のコードを変更し、何も変わらず、 'actual.Value'は常にfalseです! –

関連する問題