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# 具有授权ASP.NET Core 2.0 Web API的单元测试控制器_C#_Unit Testing_Asp.net Core_Moq - Fatal编程技术网

C# 具有授权ASP.NET Core 2.0 Web API的单元测试控制器

C# 具有授权ASP.NET Core 2.0 Web API的单元测试控制器,c#,unit-testing,asp.net-core,moq,C#,Unit Testing,Asp.net Core,Moq,我有一个控制器: public class InvitationsController: Controller { private readonly IMapper _mapper; private readonly IInvitationManager _invitationManager; private readonly UserManager<MyAppUser> _userManager; public In

我有一个控制器:

public class InvitationsController: Controller {
        private readonly IMapper _mapper;
        private readonly IInvitationManager _invitationManager;
        private readonly UserManager<MyAppUser> _userManager;

        public InvitationsController(
            IInvitationManager invitationManager,
            IMapper mapper,
            UserManager<MyAppUser> userManager,
            IJobManager jobManager
        ) {
            _invitationManager = invitationManager;
            _mapper = mapper;
            _userManager = userManager;
        } 
[Authorization]
GetInvitationByCode(string code) { ... }
内容如下:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException:“无法实例化类的代理:Microsoft.AspNetCore.Identity.UserManager`1[[MyApp.api.Core.Models.MyAppUser,MyApp.api,版本=1.0.0.0,区域性=中性,PublicKeyToken=null]]。
找不到无参数构造函数。“

我想,问题在于依赖项注入。在Startups.cs文件中,您可以找到类似的字符串:
services.AddIdentity

您不是单元测试;您正在进行集成测试。当你发现自己设置了一万个mock只是为了运行一个方法时,这是一个很好的迹象,这是一个集成测试。此外,授权之类的事情只在请求生命周期中发生;如果不执行实际的请求,就无法进行测试,这同样意味着您正在进行集成测试

因此,请使用

private readonly TestServer\u服务器;
私有只读HttpClient\u客户端;
公共MyTestClass()
{
_服务器=新的TestServer(新的WebHostBuilder()
.UseStartup());
_client=_server.CreateClient();
}
[事实]
公共异步任务GetInvitationByCode_ReturnsInvitation(){
var mockInvitation=新邀请{
StoreId=1,
InviteCode=“123abc”,
};
var response=wait_client.GetAsync(“/route”);
response.EnsureSuccessStatusCode();
var responseString=await response.Content.ReadAsStringAsync();
var result=JsonConvert.DeserializeObject(responseString);
//比较您关心的各个属性。
//由于引用不平等,比较完整对象将失败
Assert.Equal(mockInvitation.StoreId,result.StoreId);
}

如果需要构建数据以返回正确的结果,只需使用。将其用于集成测试的最简单方法是指定一个新环境,如“Test”。然后,在启动时,在配置上下文时,在环境为“测试”时,在环境上进行分支,并使用内存中的提供程序(而不是SQL Server或其他什么)。然后,在为集成测试设置测试服务器时,只需在
之前添加
.UseEnvironment(“test”)
。UseStartup()

UserManager
是一个应该抽象出来的实现问题。将使模拟和注入更容易。在测试控制器类时,您将无法测试
AuthorizationAttribute
的实际工作。因为中间件使用了
AuthorizationAttribute
。对于需要测试完整管道的测试:创建客户端(
HttpClient
),启动WebAPI,将请求发送到正在测试的url,并在响应时断言。在测试控制器及其方法时,您是否推荐集成测试方法而不是单元测试?控制器操作,是。如果你的控制器上有某种实用方法,而不是一个动作,你可以对它进行单元测试。行动本质上是整合。除非你通过请求点击它,否则你不会知道它是否真的在工作。这个答案确实让我走上了正确的轨道,但是你如何“伪造”经过身份验证的用户,以便你可以运行一个显示授权通过的测试?ie如何测试应用的授权属性?ie[Authorize(Policy=“Is18orOlder”)]或任何策略?将一个或多个测试用户插入内存数据库。然后,使用测试客户端点击login post操作,并为要测试的用户发送用户名和密码。响应将包含您的身份验证cookie。使用它再次通过测试客户端发出经过身份验证的请求。根据被测试的用户,断言授权相应地通过或失败。
  public class InvitationsControllerTests {

    private Mock<IInvitationManager> invitationManagerMock;        
    private Mock<UserManager<MyAppUser>> userManagerMock;
    private Mock<IMapper> mapperMock;
    private InvitationsController controller;

    public InvitationsControllerTests() {
        invitationManagerMock = new Mock<IInvitationManager>();          
        userManagerMock = new Mock<UserManager<MyAppUser>>();

        mapperMock = new Mock<IMapper>();
        controller = new InvitationsController(invitationManagerMock.Object,
                   mapperMock.Object,
                   userManagerMock.Object);
    }

    [Fact]
    public async Task GetInvitationByCode_ReturnsInvitation() {

        var mockInvitation = new Invitation {
            StoreId = 1,
            InviteCode = "123abc",
        };

        invitationManagerMock.Setup(repo => 
        repo.GetInvitationByCodeAsync("123abc"))
            .Returns(Task.FromResult(mockInvitation));

        var result = await controller.GetInvitationByCode("123abc");

        Assert.Equal(mockInvitation, result);
    }
        controller = new InvitationsController(invitationManagerMock.Object,
                   mapperMock.Object,
                   userManagerMock.Object);
private readonly TestServer _server;
private readonly HttpClient _client;

public MyTestClass()
{
    _server = new TestServer(new WebHostBuilder()
        .UseStartup<Startup>());
    _client = _server.CreateClient();
}

[Fact]
public async Task GetInvitationByCode_ReturnsInvitation() {

    var mockInvitation = new Invitation {
        StoreId = 1,
        InviteCode = "123abc",
    };

    var response = await _client.GetAsync("/route");
    response.EnsureSuccessStatusCode();

    var responseString = await response.Content.ReadAsStringAsync();
    var result = JsonConvert.DeserializeObject<Invitation>(responseString);

    // Compare individual properties you care about.
    // Comparing the full objects will fail because of reference inequality
    Assert.Equal(mockInvitation.StoreId, result.StoreId);
}