如何为包含异步服务调用的RelayCommand编写单元测试?

时间:2015-09-18 10:52:47

标签: c# unit-testing testing nunit relaycommand

我有一个RelayCommand我正在尝试测试。 RelayCommand包含Service Call来验证我的用户。如下所示:

private MvxCommand _signIn;
public MvxCommand SignIn
{
    get
    {
        return _signIn ?? (_signIn = new MvxCommand(() =>
        {
            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
            EndpointAddress endpoint = new EndpointAddress(AppResources.AuthService);
            var client = new MyService(binding, endpoint);
            client.AuthorizeCompleted += ((sender, args) =>
            {
                try
                {
                    if (args.Result)
                    {
                        //Success.. Carry on
                    }
                }
                catch (Exception ex)
                {
                    //AccessDenied Exception thrown by service
                    if (ex.InnerException != null && string.Equals(ex.InnerException.Message, "Access is denied.", StringComparison.CurrentCultureIgnoreCase))
                    {
                        //Display Message.. Incorrect Credentials
                    }
                    else
                    {
                        //Other error... Service down?
                    }
                }
            });

            client.AuthorizeAsync(UserName, Password, null);

        }));
    }
}

但现在我正在使用NUnit来测试我的ViewModels,而我对如何测试RelayCommand

感到困惑

我能做到:

[Test]
public void PerformTest()
{
    ViewModel.SignIn.Execute();
}

但是这不返回SignIn方法是否成功的信息。

如何测试包含RelayCommand的{​​{1}}?

1 个答案:

答案 0 :(得分:1)

所以最后我使用Dependency Injection将一个服务注入到我的viewmodel的构造函数中,如下所示:

public IMyService client { get; set; }

public MyClass(IMyService myservice)
{
    client = myservice
}

然后我可以重构我的SignIn方法:

private MvxCommand _signIn;
public MvxCommand SignIn
{
    get
    {
        return _signIn ?? (_signIn = new MvxCommand(() =>
        {
            client.AuthorizeCompleted += ((sender, args) =>
            {
                try
                {
                    if (args.Result)
                    {
                        //Success.. Carry on
                    }
                }
                catch (Exception ex)
                {
                    //AccessDenied Exception thrown by service
                    if (ex.InnerException != null && string.Equals(ex.InnerException.Message, "Access is denied.", StringComparison.CurrentCultureIgnoreCase))
                    {
                        //Display Message.. Incorrect Credentials
                    }
                    else
                    {
                        //Other error... Service down?
                    }
                }
            });
            client.AuthorizeAsync(UserName, Password, null); 
        }));
    }
}

使用Assign-Act-Assert设计模式使用模拟服务测试我的ViewModel

    [Test]
    public void PerformTest()
    {
        List<object> objs = new List<object>();
        Exception ex = new Exception("Access is denied.");
        objs.Add(true);

        AuthorizeCompletedEventArgs incorrectPasswordArgs = new AuthorizeCompletedEventArgs(null, ex, false, null);
        AuthorizeCompletedEventArgs correctPasswordArgs = new AuthorizeCompletedEventArgs(objs.ToArray(), null, false, null);

        Moq.Mock<IMyService> client = new Mock<IMyService>();

        client .Setup(t => t.AuthorizeAsync(It.Is<string>((s) => s == "correct"), It.Is<string>((s) => s == "correct"))).Callback(() =>
        {
            client.Raise(t => t.AuthorizeCompleted += null, correctPasswordArgs);
        });


        client.Setup(t => t.AuthorizeAsync(It.IsAny<string>(), It.IsAny<string>())).Callback(() =>
        {
            client.Raise(t => t.AuthorizeCompleted += null, incorrectPasswordArgs);
        });

        var ViewModel = new MyClass(client.Object);

        ViewModel.UserName = "correct";
        ViewModel.Password = "correct";
        ViewModel.SignIn.Execute();
    }
相关问题