【问题标题】:Unit testing a void method with a background worker that calls another method?使用调用另一个方法的后台工作人员对 void 方法进行单元测试?
【发布时间】:2013-11-19 18:02:01
【问题描述】:

请记住,我对单元测试还很陌生,所以请多多包涵。我有一个方法,它使用后台工作者来调用我的解决方案中另一个项目中的类的方法,我发现很难集中精力进行单元测试。

这基本上是该方法的作用:

public void VerifyLocation()
{
    this.IsBusy = true;

    using (BackgroundWorker worker = new BackgroundWorker())
    {
        worker.DoWork += (sender, e) =>
        {
            Context context = Profile.GetContext();

            AssetManagerService svc = new AssetManagerService(context);
            this.Status = svc.Login();

            if (this.Status == AssetManagerLoginStatus.Success)
            {
                //Do stuff
                this.ShowError = false;
            }
            else if (this.Status == AssetManagerLoginStatus.LocationDoesNotExst || this.Status == AssetManagerLoginStatus.LibraryTitleNotDetermined)
                this.ShowError = true;
            else
                this.ShowError = false;
        };

        worker.RunWorkerCompleted += (sender, e) =>
        {
            if (e.Error != null)
            {
                this.ShowError = true;
            }

            this.IsBusy = false;
        };

        worker.RunWorkerAsync();
    }
}

这是AssetManagerService 的样例:

public class AssetManagerService
{
    //AssetManager is an abstract class
    private AssetManager provider = null;

    public AssetManagerService(UnityContext context)
    {
        this.Context = context;
        this.InitializeProvider();
    }

    private void InitializeProvider()
    {
        //Determine provider based on Context properties
    }

    public AssetManagerLoginStatus Login()
    {
        return this.provider.Login();
    }
}

显然我最关心的是调用了Login() 方法。我会使用Shim 来控制DoWork 期间发生的事情吗?我会使用Stub 强制Login() 返回特定值吗?这两个概念对我来说都很新。是否需要进行重构以使其更具单元测试性?如果是这样,需要进行哪些更改?

【问题讨论】:

  • 您使用的 Visual Studio 版本是什么?似乎是 MS Fakes 的不错候选者。

标签: c# unit-testing visual-studio-2012 refactoring


【解决方案1】:

我会将 DoWork 移到一个单独的方法中,因为这样测试它比尝试测试异步/多线程代码要容易得多。

如果您只需要测试登录是否称为模拟/垫片可能是要走的路。此外,通过构造函数将 AssetManager 模拟注入 AssetManagerService 实例会更容易。

此外,模拟接口更容易。也许你可以从 AssetManager 中提取一个接口,模拟它并通过构造函数将它注入到 AssetManagerInstance 中。要模拟一个界面,您不一定需要 shim。像 NSubstitute 这样更简单的模拟框架就可以完成这项工作。使用 NSubstitute 你还可以告诉你的 mock 在 Login() 被调用时返回一个特定的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多