Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.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

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# 如何模拟(MOQ)已密封安装程序AbstractAcquireTokenParameterBuilder的IConfidentialClientApplication?_C#_Unit Testing_.net Core_Moq_Msal - Fatal编程技术网

C# 如何模拟(MOQ)已密封安装程序AbstractAcquireTokenParameterBuilder的IConfidentialClientApplication?

C# 如何模拟(MOQ)已密封安装程序AbstractAcquireTokenParameterBuilder的IConfidentialClientApplication?,c#,unit-testing,.net-core,moq,msal,C#,Unit Testing,.net Core,Moq,Msal,尝试为IConfidentialClientApplication设置moq时出现以下异常: System.NotSupportedException:不支持的表达式:…=> ..…ExecuteAsync()不可重写的成员(此处: AbstractAcquireTokenParameterBuilder.ExecuteAsync) 不能在设置/验证表达式中使用 private Mock_appMock=new Mock(); [事实] 公共异步任务GetAccessTokenResultAsy

尝试为
IConfidentialClientApplication
设置moq时出现以下异常:

System.NotSupportedException:不支持的表达式:…=> ..…ExecuteAsync()不可重写的成员(此处: AbstractAcquireTokenParameterBuilder.ExecuteAsync) 不能在设置/验证表达式中使用

private Mock_appMock=new Mock();
[事实]
公共异步任务GetAccessTokenResultAsync_with GoodSetup_ReturnsToken()
{
//利用用于测试中模拟的MSAL AuthenticationResult构造函数
var authentication=CreateAuthenticationResult();
//这里抛出异常
_appMock.Setup(\u=>\ u0.AcquireTokenForClient(It.IsAny()).ExecuteAsync())
.ReturnsAsync(身份验证);
…剩下的测试。。。
}
返回一个
AcquireTokenForClientParameterBuilder
。AcquireTokenForClient
;“一个生成器,允许您在执行令牌请求之前添加可选参数”,所以我不能轻易地模仿这个棘手的物体


对于那些好奇的人来说,
CreateAuthenticationResult()
是一种从Microsoft.Identity.Client.AuthenticationResult调用签名的方法,Microsoft专门添加了该签名,用于存根
AuthenticationResult
,因为它也是一个密封的类,所以不能被模拟


鉴于
AcquireTokenForClientParameterBuilder
是通过外部库提供的,您显然无法将其修改为更易于测试。考虑到这一点,我建议将代码抽象到您自己的接口后面(类似于将适配器模式应用于测试目的)

以以下服务/测试为例,说明您当前如何使用IConfidentialClientApplication并尝试模拟它(这会导致与您看到的相同错误):

公共类MyService
{
私有只读IConfidentialClientApplication _机密客户端应用程序;
公共MyService(IConfidentialClientApplication机密客户端应用程序)
{
_机密客户端应用程序=机密客户端应用程序;
}
公共异步任务GetAccessToken(IEnumerable作用域)
{
AcquireTokenForClientParameterBuilder tokenBuilder=\u机密客户端应用程序。AcquireTokenForClient(作用域);
AuthenticationResult token=等待tokenBuilder.ExecuteAsync();
返回token.AccessToken;
}
}
公共类UnitTest1
{
[事实]
公共异步任务Test1()
{
Mock _appMock=新建Mock();
AuthenticationResult authentication=CreateAuthenticationResult(“myToken”);
_appMock
.Setup(=>u.AcquireTokenForClient(It.IsAny()).ExecuteAsync())
.ReturnsAsync(身份验证);
var myService=newmyservice(_appMock.Object);
string accessToken=wait myService.GetAccessToken(新字符串[]{});
Assert.Equal(“myToken”,accessToken);
}
私有身份验证结果CreateAuthenticationResult(字符串accessToken)=>
新的AuthenticationResult(accessToken、true、null、DateTimeOffset.Now、DateTimeOffset.Now、string.Empty、null、null、null、Guid.Empty);
}
通过引入单独的接口,您的代码可以简单地依赖于此,让您控制如何使用/测试它:

public interface IIdentityClientAdapter
{
    Task<string> GetAccessToken(IEnumerable<string> scopes);
}

public class IdentityClientAdapter : IIdentityClientAdapter
{
    private readonly IConfidentialClientApplication _confidentialClientApplication;

    public IdentityClientAdapter(IConfidentialClientApplication confidentialClientApplication)
    {
        _confidentialClientApplication = confidentialClientApplication;
    }

    public async Task<string> GetAccessToken(IEnumerable<string> scopes)
    {
        AcquireTokenForClientParameterBuilder tokenBuilder = _confidentialClientApplication.AcquireTokenForClient(scopes);
        AuthenticationResult token = await tokenBuilder.ExecuteAsync();
        return token.AccessToken;
    }
}

public class MyService
{
    private readonly IIdentityClientAdapter _identityClientAdapter;

    public MyService(IIdentityClientAdapter identityClientAdapter)
    {
        _identityClientAdapter = identityClientAdapter;
    }

    public async Task<string> GetAccessToken(IEnumerable<string> scopes)
    {
        return await _identityClientAdapter.GetAccessToken(scopes);
    }
}

public class UnitTest1
{
    [Fact]
    public async Task Test1()
    {
        Mock<IIdentityClientAdapter> _appMock = new Mock<IIdentityClientAdapter>();
        _appMock
            .Setup(_ => _.GetAccessToken(It.IsAny<string[]>()))
            .ReturnsAsync("myToken");

        var myService = new MyService(_appMock.Object);
        string accessToken = await myService.GetAccessToken(new string[] { });

        Assert.Equal("myToken", accessToken);
    }
}
公共接口IIdentialClientAdapter
{
任务GetAccessToken(IEnumerable作用域);
}
公共类IdentityClientAdapter:IIdentialClientAdapter
{
私有只读IConfidentialClientApplication _机密客户端应用程序;
公共标识客户端适配器(IConfidentialClientApplication机密客户端应用程序)
{
_机密客户端应用程序=机密客户端应用程序;
}
公共异步任务GetAccessToken(IEnumerable作用域)
{
AcquireTokenForClientParameterBuilder tokenBuilder=\u机密客户端应用程序。AcquireTokenForClient(作用域);
AuthenticationResult token=等待tokenBuilder.ExecuteAsync();
返回token.AccessToken;
}
}
公共类MyService
{
专用只读IIdentialClientAdapter_identityClientAdapter;
公共MyService(IIdentialClientAdapter identityClientAdapter)
{
_identityClientAdapter=identityClientAdapter;
}
公共异步任务GetAccessToken(IEnumerable作用域)
{
返回wait_identityClientAdapter.GetAccessToken(作用域);
}
}
公共类UnitTest1
{
[事实]
公共异步任务Test1()
{
Mock _appMock=新建Mock();
_appMock
.Setup(=>u.GetAccessToken(It.IsAny()))
.ReturnsAsync(“myToken”);
var myService=newmyservice(_appMock.Object);
string accessToken=wait myService.GetAccessToken(新字符串[]{});
Assert.Equal(“myToken”,accessToken);
}
}

这个例子显然是微不足道的,但仍然应该适用。接口只需要适合您的需要。

您是否可以包含从
AcquireTokenForClient()返回的类型定义。
?似乎需要为该类型创建一个单独的模拟/存根,并让它从
ExecuteAsync()
@devNull
AcquireTokenForClient()
返回
AcquireTokenForClientParameterBuilder
返回身份验证。我更新了我的答案,以便更好地解释这一点。
public class MyService
{
    private readonly IConfidentialClientApplication _confidentialClientApplication;

    public MyService(IConfidentialClientApplication confidentialClientApplication)
    {
        _confidentialClientApplication = confidentialClientApplication;
    }

    public async Task<string> GetAccessToken(IEnumerable<string> scopes)
    {
        AcquireTokenForClientParameterBuilder tokenBuilder = _confidentialClientApplication.AcquireTokenForClient(scopes);
        AuthenticationResult token = await tokenBuilder.ExecuteAsync();
        return token.AccessToken;
    }
}

public class UnitTest1
{
    [Fact]
    public async Task Test1()
    {
        Mock<IConfidentialClientApplication> _appMock = new Mock<IConfidentialClientApplication>();
        AuthenticationResult authentication = CreateAuthenticationResult("myToken");
        _appMock
            .Setup(_ => _.AcquireTokenForClient(It.IsAny<string[]>()).ExecuteAsync())
            .ReturnsAsync(authentication);

        var myService = new MyService(_appMock.Object);
        string accessToken = await myService.GetAccessToken(new string[] { });

        Assert.Equal("myToken", accessToken);
    }

    private AuthenticationResult CreateAuthenticationResult(string accessToken) => 
        new AuthenticationResult(accessToken, true, null, DateTimeOffset.Now, DateTimeOffset.Now, string.Empty, null, null, null, Guid.Empty);
}
public interface IIdentityClientAdapter
{
    Task<string> GetAccessToken(IEnumerable<string> scopes);
}

public class IdentityClientAdapter : IIdentityClientAdapter
{
    private readonly IConfidentialClientApplication _confidentialClientApplication;

    public IdentityClientAdapter(IConfidentialClientApplication confidentialClientApplication)
    {
        _confidentialClientApplication = confidentialClientApplication;
    }

    public async Task<string> GetAccessToken(IEnumerable<string> scopes)
    {
        AcquireTokenForClientParameterBuilder tokenBuilder = _confidentialClientApplication.AcquireTokenForClient(scopes);
        AuthenticationResult token = await tokenBuilder.ExecuteAsync();
        return token.AccessToken;
    }
}

public class MyService
{
    private readonly IIdentityClientAdapter _identityClientAdapter;

    public MyService(IIdentityClientAdapter identityClientAdapter)
    {
        _identityClientAdapter = identityClientAdapter;
    }

    public async Task<string> GetAccessToken(IEnumerable<string> scopes)
    {
        return await _identityClientAdapter.GetAccessToken(scopes);
    }
}

public class UnitTest1
{
    [Fact]
    public async Task Test1()
    {
        Mock<IIdentityClientAdapter> _appMock = new Mock<IIdentityClientAdapter>();
        _appMock
            .Setup(_ => _.GetAccessToken(It.IsAny<string[]>()))
            .ReturnsAsync("myToken");

        var myService = new MyService(_appMock.Object);
        string accessToken = await myService.GetAccessToken(new string[] { });

        Assert.Equal("myToken", accessToken);
    }
}