Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.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中使用Moq实现模拟接口#_C#_Xamarin.forms_Moq_Xamarin.uitest - Fatal编程技术网

C# 在C中使用Moq实现模拟接口#

C# 在C中使用Moq实现模拟接口#,c#,xamarin.forms,moq,xamarin.uitest,C#,Xamarin.forms,Moq,Xamarin.uitest,我正在尝试使用Moq编写Xamarin.Forms UI测试来模拟我的身份验证接口:[上一个问题][1]。我已经重构了我的应用程序,因此我的SignIn(字符串用户名、字符串密码)方法位于实现IAuthService的类中。我现在在模拟IAuthService以基本上“替换”单击sign-in按钮时发生的实际登录验证时遇到问题。在我的CloudAuthService类(实现了IAuthService)中,我正在对Amazon Cognito进行身份验证,但我想在UI测试中模拟这个结果,这样它就不

我正在尝试使用Moq编写Xamarin.Forms UI测试来模拟我的身份验证接口:[上一个问题][1]。我已经重构了我的应用程序,因此我的
SignIn(字符串用户名、字符串密码)
方法位于实现
IAuthService
的类中。我现在在模拟
IAuthService
以基本上“替换”单击
sign-in
按钮时发生的实际登录验证时遇到问题。在我的
CloudAuthService
类(实现了
IAuthService
)中,我正在对Amazon Cognito进行身份验证,但我想在UI测试中模拟这个结果,这样它就不会调用云服务

编辑:经过多次建议,我决定将我当前的实现包括在下面。尽管出现了问题,但这似乎仍然无法完全发挥作用
Console.WriteLine(App.AuthApi.IsMockService())的输出beforeachtest()
方法中的code>会导致
true
(如预期的那样)。 但是,在
App()
构造函数方法中运行相同的操作会导致
false
。因此,它似乎没有在应用程序实际启动之前运行,有没有办法让UITest代码在应用程序初始化之前运行

登录页面

[XamlCompilation(XamlCompilationOptions.Compile)]
public sealed partial class LoginPage
{
    private readonly IBiometricAuthentication _bioInterface;

    private static readonly Lazy<LoginPage>
        Lazy =
            new Lazy<LoginPage>
                (() => new LoginPage(App.AuthApi));

    public static LoginPage Instance => Lazy.Value;

    private string _username;

    private string _password;

    private LoginPageViewModel _viewModel;

    private IAuthService _authService;

    public LoginPage(IAuthService authService)
    {
        InitializeComponent();
        _authService = authService;

        _viewModel = new LoginPageViewModel();

        BindingContext = _viewModel;
    }

    private void LoginButtonClicked(object sender, EventArgs args)
    {
          _username = UsernameEntry.Text;
          _password = PasswordEntry.Text;
          LoginToApplication();
    }

    public async void LoginToApplication()
    {
          AuthenticationContext context = await _authService.SignIn(_username, _password);
    }
}
测试类

public partial class App
{
    public static IAuthService AuthApi { get; set; } = new AWSCognito()
    public App()
    {
        Console.WriteLine(AuthApi.IsMockService())
        // AuthApi = new AWSCognito(); // AWSCognito implements IAuthService
        InitializeComponent();
        MainPage = new NavigationPage(new LoginPage(AuthApi));
    }
}
class LoginPageTest
{
    IApp app;
    readonly Platform platform;

    public LoginPageTest(Platform platform)
    {
        this.platform = platform;
    }

    [SetUp]
    public void BeforeEachTest()
    {

        var mocker = new Mock<IAuthService>();

        var response = new AuthenticationContext(CognitoResult.Ok)
        {
            IdToken = "SUCCESS_TOKEN"
        };
        mocker.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(() => new MockAuthService().SignIn("a", "a"));
        mocker.Setup(x => x.IsMockService()).Returns(() => new MockAuthService().IsMockService());
        App.AuthApi = mocker.Object;
        Console.WriteLine(App.AuthApi.IsMockService());

        app = AppInitializer.StartApp(platform);
    }


    [Test]
    public void ClickingLoginWithUsernameAndPasswordStartsLoading()
    {
        app.WaitForElement(c => c.Marked("Welcome"));
        app.EnterText(c => c.Marked("Username"), new string('a', 1));
        app.EnterText(c => c.Marked("Password"), new string('a', 1));

        app.Tap("Login");

        bool state = app.Query(c => c.Class("ProgressBar")).FirstOrDefault().Enabled;

        Assert.IsTrue(state);
    }
}
classloginpagetest
{
IApp应用程序;
只读平台;
公共登录测试(平台)
{
这个平台=平台;
}
[设置]
每个测试前的公共无效()
{
var mocker=new Mock();
var response=newauthenticationcontext(CognitoResult.Ok)
{
IdToken=“成功\u令牌”
};
mocker.Setup(x=>x.SignIn(It.IsAny(),It.IsAny())。返回(()=>newmockauthservice().SignIn(“a”,“a”));
mocker.Setup(x=>x.IsMockService())。返回(()=>newmockauthservice().IsMockService());
App.AuthApi=mocker.Object;
Console.WriteLine(App.AuthApi.IsMockService());
app=AppInitializer.StartApp(平台);
}
[测试]
public void单击带有用户名和密码的登录开始加载()
{
app.WaitForElement(c=>c.Marked(“欢迎”);
app.EnterText(c=>c.Marked(“用户名”),新字符串('a',1));
app.EnterText(c=>c.Marked(“密码”),新字符串('a',1));
点击应用程序(“登录”);
bool state=app.Query(c=>c.Class(“ProgressBar”)).FirstOrDefault()已启用;
断言。IsTrue(州);
}
}

您的问题似乎是在运行测试后注入了模拟。这意味着它在执行时使用的是原始的AuthService。如果我们重新安排代码,在执行任何操作之前移动注入,我们应该看到预期的结果:

//让我们把这个模拟注入带到这里
var mocker=new Mock();
mocker.Setup(x=>x.SignIn(It.IsAny(),It.IsAny())。返回(Task.FromResult(response)).Verifiable();
App.AuthApi=mocker.Object;
//现在我们尝试登录,它应该调用auth服务的mock方法
app.WaitForElement(c=>c.Marked(“欢迎来到Manuly!”);
app.EnterText(c=>c.Marked(“用户名”),新字符串('a',1));
app.EnterText(c=>c.Marked(“密码”),新字符串('a',1));
点击应用程序(“登录”);
var response=newauthenticationcontext(CognitoResult.Ok)
{
IdToken=“成功\u令牌”,
};
bool state=app.Query(c=>c.Class(“ProgressBar”)).FirstOrDefault()已启用;
断言。IsTrue(州);
现在尝试执行它,它应该按照您的意愿执行

编辑: 正如Nkosi在评论中指出的,静态身份验证服务是在构造函数中设置的,以防止出现这种情况

因此,这也需要改变:

公共部分类应用程序
{
public static IAuthService AuthApi{get;set;}=new AWSCognito();//在此处静态分配
公共应用程序()
{

//AuthApi=新的AWSCognito();在本例中,我只是测试应用程序在单击登录按钮后是否显示加载栏。我试图模拟
IAuthService
,以便应用程序不会调用Amazon Cognito服务。我将用完整的测试实现更新问题。您没有使用模拟。这使得它不相关。为了让您你的代码是可测试的,
app
必须通过一种机制获取它的
\u authService
成员,这种机制允许它被调出。@AluanHaddad这是有意义的。因此,如果我构造
LoginPage
以便它以某种形式通过
IAuthService
实例,那么理论上我应该能够调出这个服务对于模拟服务?@itcoder,注入需要在您尝试设置该全局属性之前进行。此时该实例可能已经创建。请注意,要在主题中考虑,因此问题必须包括内联代码(正如@Nkosi指出的)这是一个只有代码作者才可以执行的编辑,因为许可限制——所以至少需要许可证,因此大多数情况下都不能由非作者来完成。考虑这个问题以避免进一步的下票/关闭选票。有趣的是,这是有意义的。它似乎还没有取代Orgi。nal即使在这种情况下也是如此,这很奇怪。这可能与我在
登录页面上使用Singleton模式有关,但我不确定。啊,是的,只是看到了使用静态初始化充其量是次优的。它使测试变得脆弱,并且通过一个可变静态属性为一个服务注入无法泛化。Agreed,这很难看。我强烈推荐一个静态单例IoC容器(例如TinyIoC),它可以用模拟依赖项进行设置。谢谢你的建议。出于某种原因,上面的实现仍然无法工作,原始AuthService仍在调用中。我将研究TinyIoC。