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# 正确实施单元测试_C#_Unit Testing_Signalr - Fatal编程技术网

C# 正确实施单元测试

C# 正确实施单元测试,c#,unit-testing,signalr,C#,Unit Testing,Signalr,我第一次练习写单元测试,我有一些问题。首先,我将解释我要测试的内容 我想测试一个如下所示的方法: public bool IsAdmin(HubCallerContext hubCallerContext) { return hubCallerContext.User.IsInRole("admin"); } 该方法在类UserService中实现,该类连接到接口IUserService 我正在尝试创建两个测试: 具有HubCallerContext的一个,其角色为“admin”,并

我第一次练习写单元测试,我有一些问题。首先,我将解释我要测试的内容

我想测试一个如下所示的方法:

public bool IsAdmin(HubCallerContext hubCallerContext)
{
    return hubCallerContext.User.IsInRole("admin");
}
该方法在类
UserService
中实现,该类连接到接口
IUserService

我正在尝试创建两个测试:

  • 具有HubCallerContext的一个,其角色为“admin”,并将断言true
  • 具有HubCallerContext的一个,其角色为“用户”,并将断言为false
我在我的解决方案中创建了一个新类库,在这里我引用了我正在测试的项目。我安装了NUnit和Moq,并创建了一个测试类,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;

namespace ChatProj.Tests
{
    [TestFixture]
    public class Class1
    {

        [SetUp]
        public void Setup()
        {

        }

        [Test]
    public void IsAdmin_CalledByAdmin_ReturnTrue()
    {
        UserService userService = new UserService();
        bool result = userService.IsAdmin( ? );
        Assert.IsTrue( result, "Something is wrong." );
    }

    [Test]
    public void IsAdmin_CalledByUser_ReturnFalse()
    {
        UserService userService = new UserService();
        bool result = userService.IsAdmin( ? );
        Assert.IsFalse( result, "Something is wrong." );
    }

    }
}
    [Test]
    public void IsAdmin_CalledByAdminUser_ReturnTrue()
    {
        //Arrange
        var principalMock = new Mock<IPrincipal>();
        principalMock.Setup(x => x.IsInRole("admin")).Returns(true);

        //Act
        var userService = ...// create an instance of userService here
        var result = userService.IsAdmin(principalMock);

        //Assert
        Assert.IsTrue(result);
    }

    [Test]
    public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
    {
        //Arrange
        var principalMock = new Mock<IPrincipal>();
        principalMock.Setup(x => x.IsInRole("admin")).Returns(false);

        //Act
        var userService = ...// create an instance of userService here
        var result = userService.IsAdmin(principalMock);

        //Assert
        Assert.IsFalse(result);
    }
我开始感到困惑。(我已经用“?”标记了IsAdmin调用的参数,因为我不确定要在那里放什么。)

我读过关于模仿、存根、赝品和假人的书,但这些定义太抽象了,我无法真正理解。例如,我找到了以下定义:

 - Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.

 - Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).

 - Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.

 - Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
在设计测试类时,我需要某种类型的替换来替换HubCallerContext。这是假设我以正确的方式测试“IsAdmin”方法

因此,我的问题是:

  • 我是否以良好的方式测试“IsAdmin”方法

  • 我怎样才能让测试真正起作用呢?我是否使用模拟,在这种情况下,你能告诉我如何实现它,或者给我指出正确的方向吗


您可以获得角色列表,并使用
foreach
检查每个角色,假设
HubCallerContext
就是这个角色,那么设置测试将很容易。您只需要对
IPrincipal
进行两次模拟,其中一次对
.IsInRole(“admin”)
调用返回true,另一次返回false。请将这两次模拟包装在
IRequest
的模拟中

根据所使用的模拟框架,语法会有所不同,但您的测试将以如下方式结束:

[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
    UserService userService = new UserService();
    var principalMock = new Mock<IPrincipal>();
    principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
    var requestMock = new Mock<IRequest>();
    requestMock.Setup(x => x.User).Returns(principalMock.Object);
    var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
    Assert.IsTrue( result, "Something is wrong." );
}

[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
    UserService userService = new UserService();
    var principalMock = new Mock<IPrincipal>();
    principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
    var requestMock = new Mock<IRequest>();
    requestMock.Setup(x => x.User).Returns(principalMock.Object);
    var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
    Assert.IsFalse( result, "Something is wrong." );
}
[测试]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService UserService=new UserService();
var principalMock=new Mock();
principamLock.Setup(x=>x.IsInRole(“admin”))。返回(true);
var requestMock=new Mock();
Setup(x=>x.User).Returns(principalMock.Object);
var result=userService.IsAdmin(新的HubCallerContext(requestMock.Object“”);
IsTrue(结果,“有什么地方不对劲了”);
}
[测试]
public void IsAdmin_calledbyser_ReturnFalse()
{
UserService UserService=new UserService();
var principalMock=new Mock();
principamLock.Setup(x=>x.IsInRole(“admin”))。返回(false);
var requestMock=new Mock();
Setup(x=>x.User).Returns(principalMock.Object);
var result=userService.IsAdmin(新的HubCallerContext(requestMock.Object“”);
Assert.IsFalse(结果是“有什么不对劲了”);
}

我没有检查上面的方法是否编译,但它是基于所需的语法的。

我认为如果您稍微更改一下测试中的方法(假设它不是遗留代码的一部分),编写这两个单元测试会容易得多

如果以这种方式定义方法:

public bool IsAdmin(IPrincipal user)
{
    return user.IsInRole("admin");
}
事情会变得非常简单(顺便说一句,检查“德米特定律”))。您可以传入一个模拟对象(因为用户参数是interface-IPrincipal),如果用户应该是“admin”角色,则返回true,否则返回false

此解决方案的好处是,您不必构建模拟对象的图形,并且测试的排列部分非常简单。您的测试可能看起来有点像这样:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;

namespace ChatProj.Tests
{
    [TestFixture]
    public class Class1
    {

        [SetUp]
        public void Setup()
        {

        }

        [Test]
    public void IsAdmin_CalledByAdmin_ReturnTrue()
    {
        UserService userService = new UserService();
        bool result = userService.IsAdmin( ? );
        Assert.IsTrue( result, "Something is wrong." );
    }

    [Test]
    public void IsAdmin_CalledByUser_ReturnFalse()
    {
        UserService userService = new UserService();
        bool result = userService.IsAdmin( ? );
        Assert.IsFalse( result, "Something is wrong." );
    }

    }
}
    [Test]
    public void IsAdmin_CalledByAdminUser_ReturnTrue()
    {
        //Arrange
        var principalMock = new Mock<IPrincipal>();
        principalMock.Setup(x => x.IsInRole("admin")).Returns(true);

        //Act
        var userService = ...// create an instance of userService here
        var result = userService.IsAdmin(principalMock);

        //Assert
        Assert.IsTrue(result);
    }

    [Test]
    public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
    {
        //Arrange
        var principalMock = new Mock<IPrincipal>();
        principalMock.Setup(x => x.IsInRole("admin")).Returns(false);

        //Act
        var userService = ...// create an instance of userService here
        var result = userService.IsAdmin(principalMock);

        //Assert
        Assert.IsFalse(result);
    }
[测试]
public void IsAdmin_calledbyadmin_ReturnTrue()
{
//安排
var principalMock=new Mock();
principamLock.Setup(x=>x.IsInRole(“admin”))。返回(true);
//表演
var userService=…//在此处创建userService的实例
var result=userService.IsAdmin(principalMock);
//断言
断言(结果);
}
[测试]
public void IsAdmin_calledbynonadmin_ReturnFalse()
{
//安排
var principalMock=new Mock();
principamLock.Setup(x=>x.IsInRole(“admin”))。返回(false);
//表演
var userService=…//在此处创建userService的实例
var result=userService.IsAdmin(principalMock);
//断言
Assert.IsFalse(结果);
}

我建议您阅读这一系列博文(我认为这很酷:):

我的意思是您可以从数据库中查看角色列表并调用方法IsAdmin()@somesh,但这不是真正的单元测试,不是吗?他正在寻找使用mock对象模拟对数据库的调用的示例。您已经得到了
IsInRole(“admin”)
为两个模拟返回true。为回答伙伴干杯!但出现此错误:.@JazzMaster我忘记了connectionString参数。我认为对于这些测试,可以将其设置为
。代码更新。@DavidArno现在工作得很好!添加了关于UserService声明的编辑,并移动了parantheses@
var result=UserService.IsAdmin(新的HubCallerContext(requestMock.Object,”)啊,聪明!感谢分享这种不同的方法。这个博客看起来很有趣,我得看看:)