【问题标题】:How do I write a Unit test for a RelayCommand that contains an Async Service Call?如何为包含异步服务调用的 RelayCommand 编写单元测试?
【发布时间】:2015-09-18 10:52:47
【问题描述】:

我有一个 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 方法是否成功的信息。

如何测试包含Service CallRelayCommand

【问题讨论】:

  • 对我来说,这看起来像是一个集成测试,而不是一个单元测试。您对测试哪个单元感兴趣?如果是视图模型,您可以/应该注入一个虚拟(测试)函数来测试是否发送了正确的参数。
  • 我是自动化测试的新手,但看起来你可能是对的,这可能是一个集成测试。我正在测试我的视图模型。如果我使用虚拟视图模型。这不会测试我的服务,还有其他服务测试方法吗?
  • 要测试您的视图模型,不要使用虚拟视图模式。将测试方法注入到您的视图模型中,您可以使用它来确保您的视图模型正确调用您的服务。您应该从内部调用代理服务服务本身的源应该有自己的单元测试。如果你想做端到端的集成测试,自动化将很难。抱歉,如果我有问题的答案,我会给出答案。我所能做的就是尝试更多地阐明这个问题。
  • @F5F5F5 感谢您指出正确的方向。我想我明白你在说什么,并希望很快在这里发布答案

标签: c# unit-testing testing nunit relaycommand


【解决方案1】:

所以最后我使用Dependency Injection 将服务注入到我的视图模型的构造函数中,如下所示:

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();
    }

【讨论】:

    猜你喜欢
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多