Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 测试.Net Core中的控制器是否总是返回false?_C#_Unit Testing_Asp.net Core_Moq_Xunit.net - Fatal编程技术网

C# 测试.Net Core中的控制器是否总是返回false?

C# 测试.Net Core中的控制器是否总是返回false?,c#,unit-testing,asp.net-core,moq,xunit.net,C#,Unit Testing,Asp.net Core,Moq,Xunit.net,我编写以下XUnit测试来测试.Net核心WebApi控制器的操作: namespace VistaBest.XUnitTest.Api.Test { public class Account_UnitTest { [Fact] public void ValidateUserTest() { const string username = "admin"; const string

我编写以下XUnit测试来测试.Net核心WebApi控制器的操作:

namespace VistaBest.XUnitTest.Api.Test
{
    public class Account_UnitTest
    {
        [Fact]
        public void ValidateUserTest()
        {
            const string username = "admin";
            const string password = "admin";
            var usersBusinessObjectMock = new Mock<IUsersBusinessObject>();
            usersBusinessObjectMock.Setup(service => service.ValidateUser(username, password)).Returns(() => true);
            var controller = new AccountController(usersBusinessObjectMock.Object);
            var actionResult = controller.ValidateUser(new LoginModel
            {
                Username = username,
                Password = password
            });
            var okObjectResult = Assert.IsType<OkObjectResult>(actionResult);
            var result = okObjectResult.Value as bool?;
            Assert.True(result);
        }
    }
}
IUsersBusinessObject

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()));
        }
    }
}
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;
        }
}
但是
var result=okObjectResult.Value为bool总是
false

怎么了


在阅读代码10分钟后,因为很难找到这个错误。你做的一切都对

        var okObjectResult = Assert.IsType<OkObjectResult>(actionResult);
        var result = okObjectResult.Value as bool?;
        Assert.True(result);
var-okObjectResult=Assert.IsType(actionResult);
var结果=okObjectResult.值为bool?;
断言.True(结果);
但这里有一个错误

var是危险的。。。 您的变量okObjectResult不是来自okObjectResult类型。。。这就是为什么你的断言永远不正确。。。 我肯定你不想打字

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

这将起作用,我将在您的代码中进行一些小的重构

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);
    }
  }
}
namespace VistaBest.XUnitTest.Api.Test
{
公共类帐户单元测试
{
私有只读Mock_usersBusinessObjectMock;
私有只读AccountController\u AccountController;
公共帐户单元测试()
{
_usersBusinessObjectMock=新建Mock();
_accountController=新的accountController(_usersBusinessObjectMock.Object);
}
[事实]
公共void ValidateUserTest()
{
var模型=新的LoginModel
{
Username=“admin”,
Password=“admin”
};
_usersBusinessObjectMock.Setup(service=>service.ValidateUser(model.Username,model.Password))。返回(()=>true);
var actual=_accountController.ValidateUser(model)作为OkObjectResult;
实际值应等于(真);
//或Assert.True(实际值);
}
}
}

重新检查控制器如何调用验证方法后,我意识到问题在于您没有正确配置模拟

控制器正在呼叫

_usersBusinessObject.ValidateUser(model.Username, model.Password.ToMd5Hash())
请注意,正在对密码调用
ToMd5Hash()

但是,您可以像

usersBusinessObjectMock
    .Setup(service => service.ValidateUser(username, password))
    .Returns(() => true);
看到问题了吗

mock需要的是原始密码而不是散列密码,因此在传递散列密码时不会返回
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);
usersBusinessObjectMock
.Setup(service=>service.ValidateUser(It.IsAny(),It.IsAny())
.返回(()=>true);

因此,无论您传递给mock的值是什么,它都将始终返回
true

请注意,假设将提供的对象强制转换为提供的类型。我像您编写的那样更改代码,没有任何更改,并且okObjectResult值始终为false!如果您只是将值强制转换为布尔值ie
var result=(bool)okObjectResult.value@Nkosi:结果总是错误的,请看主要帖子图片中的“手表”部分。我们关注的是错误的事情。模拟未正确配置,因此表现不符合预期。检查我提供的答案。我像你写的那样更改代码,没有任何更改,
实际值。值始终为false!太好了,非常感谢
usersBusinessObjectMock
    .Setup(service => service.ValidateUser(It.IsAny<string>(), It.IsAny<string>()))
    .Returns(() => true);