Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.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# 模拟数据访问器_C#_Unit Testing_Inversion Of Control_Moq - Fatal编程技术网

C# 模拟数据访问器

C# 模拟数据访问器,c#,unit-testing,inversion-of-control,moq,C#,Unit Testing,Inversion Of Control,Moq,我正在努力学习如何与NUnit和IoC一起使用Moq (我在BitBucket中有我的完整项目,但不确定如何共享…) 我有一个逻辑方法(登录),我正在尝试测试。它接受一个请求对象(具有用户名、密码和IP地址)。如果用户名和/或密码为空,则逻辑将返回失败状态,并且不会转到数据访问层 所以我创建了一个单元测试来测试这一点。 (这是我第一次尝试嘲弄……) public void NotNull\u返回\u True() { //安排 var请求=新登录请求{IPAddress=“1.1.1.1”,U

我正在努力学习如何与NUnit和IoC一起使用Moq

(我在BitBucket中有我的完整项目,但不确定如何共享…)

我有一个逻辑方法(登录),我正在尝试测试。它接受一个请求对象(具有用户名、密码和IP地址)。如果用户名和/或密码为空,则逻辑将返回失败状态,并且不会转到数据访问层

所以我创建了一个单元测试来测试这一点。 (这是我第一次尝试嘲弄……)

public void NotNull\u返回\u True()
{
//安排
var请求=新登录请求{IPAddress=“1.1.1.1”,Username=“dummy”,Password=“dummy”};
var response=newloginresponse{Request=Request,Success=true,Message=”“,UserID=1};
//设置moc数据访问器,因为我们不想访问具体的数据访问器。
var MockedDataAccess=new Mock();
//设置它的返回值
MockedDataAccess.Setup(x=>x.Login(请求))。返回(响应);
//使用Moc数据访问器实例化我们正在测试的逻辑类。
var逻辑=新业务逻辑(MockedDataAccess.Object);
//表演
var result=logic.Login(新的LoginRequest{Password=“dummy”,Username=“dummy”,IPAddress=“1.1.1”});
//断言
断言。相等(正确、结果、成功);
}
这在断言上失败,因为“result”为NULL

我可能做错了很多。例如,我不确定为什么我需要在顶部设置请求和响应对象,但因为我找到的所有示例都是“string”和“int”输入,似乎我无法使用它

有人能帮我理解一下吗?在断言中得到NULL的结果有什么不对?我一步一步地完成,代码按预期执行。但是结果为null,因为我从未调用过数据访问器(它使用了mock)

编辑: 啊,

//设置它的返回值
MockedDataAccess.Setup(x=>x.Login(It.IsAny())。返回(响应);

这解决了问题。我不知道为什么,所以如果你能帮助我理解并重构它,让它看起来像一个有经验的Moq/UnitTester所期望的那样,那将是非常有用的。

即使你的
请求
对象的属性值与你传递给
var result=logic.Login的属性值相同,Username=“dummy”,IPAddress=“1.1.1.1”})
,它们是不同的对象,因此您尝试使用
MockedDataAccess.Setup(x=>x.Login(request)).Returns(response)返回的值未返回

改变

var result = logic.Login(new LoginRequest { Password = "dummy", Username = "dummy", IPAddress = "1.1.1.1" });

它使用
MockedDataAccess.Setup(x=>x.Login(it.IsAny()).Returns(response)的原因
是因为现在您说的是“当调用
MockedDataAccess.Login
时,其参数值为any,返回
response

关于问题的第二部分,需要设置请求和响应对象的原因是,默认情况下,对模拟对象调用的任何方法都将返回null。下面列出的
BusinessLogic.Login
方法将返回
dataAccess.Login()
的值。由于
dataAccess
是一个模拟,因此
dataAccess.Login()
方法将返回null,除非您另行通知

    public LoginResponse Login(LoginRequest request)
    {

        // Basic validation
        if (request == null)
            return new LoginResponse
            {
                Success = false,
                Message = "Empty Request"
            };

        if (string.IsNullOrEmpty(request.Username) || string.IsNullOrEmpty(request.Password))
            return new LoginResponse
            {
                Success = false,
                Message = "Username and/or password empty"
            };

        // This is returning null since dataAccess is a mock
        return dataAccess.Login(request);
    }

你说你认为你做错了很多,但是你设置测试的方式和我差不多。我唯一要改变的事情(除了修复上面描述的
设置
方法)是为测试使用UnitOfWork\u StateUnderTest\u ExpectedBehavior命名模式。例如,
Login\u ValidLoginRequest\u应该返回validloginResponse()

此代码的问题

var result=logic.Login(新登录请求{Password=“dummy”,Username=“dummy”,IPAddress=“1.1.1.1”})

Login
方法的实现中,这被称为

dataAccess.Login(请求)

这意味着您必须为方法
Login
设置
DataAccess
的mock,否则mock什么也不做。如果模拟是假的,则需要进行设置,以便按照您需要的方式工作。在这种情况下,@Ben Rubin的答案是绝对正确的

当mock设置为这样时

MockedDataAccess.Setup(x=>x.Login(请求)).Returns(响应)

然后,有必要使用与设置数据访问
Login
方法中使用的请求完全相同的请求对象调用测试中的方法,因为否则mock将充当not setup。在这里,您基本上是说“当使用此请求调用DataAccess登录时,将返回该响应”

但是当mock是这样设置的时候

MockedDataAccess.Setup(x=>x.Login(It.IsAny())。返回(响应)

然后它就工作了,因为这里的
Login
设置为任何
LoginRequest
。因此,在这种情况下,无论使用什么请求,mock都将返回
响应。嗯


以下是有关登录方法的更多信息?它是否会调用您的
IDataAccess
依赖项上的方法,如果这些方法返回null,则返回null?@BenRubin-我添加了一个Bitbucket链接,因此您可以查看所有这些方法并进行克隆。但基本上,如果有空值发送到BL层,它将计算并返回一个成功标志为False的响应对象。它不应该返回空对象。谢谢@BenRubin-这一切都很有意义,在我的学习道路上帮助了我,并提供了一些验证。谢谢
var result = logic.Login(new LoginRequest { Password = "dummy", Username = "dummy", IPAddress = "1.1.1.1" });
var result = logic.Login(request);
    public LoginResponse Login(LoginRequest request)
    {

        // Basic validation
        if (request == null)
            return new LoginResponse
            {
                Success = false,
                Message = "Empty Request"
            };

        if (string.IsNullOrEmpty(request.Username) || string.IsNullOrEmpty(request.Password))
            return new LoginResponse
            {
                Success = false,
                Message = "Username and/or password empty"
            };

        // This is returning null since dataAccess is a mock
        return dataAccess.Login(request);
    }