使用静态变量的单元测试C#/.NET类(单元测试过程隔离) [英] Unit testing C#/.NET classes which make use of static variables (unit test process segregation)

查看:52
本文介绍了使用静态变量的单元测试C#/.NET类(单元测试过程隔离)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代码库,在很多有意义的情况下都使用静态变量,例如标记某些东西自启动以来已经运行过,等等.

I've got a codebase that makes use of static variables in a number of cases where that makes sense, for example flagging that something's already run once since launch, etc etc.

当然,这可能会导致单元测试出现问题,突然之间顺序变得很重要,并且对此类方法的测试结果可能取决于之前是否有其他代码被击中过,等等.我对TestTools.UnitTesting的理解就是说,每当我运行一组单元测试时,同一项目中的任何项目都将在同一流程中运行,因此在测试之间保持任何静态,而单元测试项目边界也暗示了一个过程边界,因此,如果我运行项目A进行了3次测试,项目B进行了第4次测试,状态从1> 2> 3(以它们运行的​​顺序)保持不变,但4是纯状态,并且默认为静态.

Of course, this can lead to issues with unit testing whereupon suddenly order matters and the outcome of a test on a method of such a class may depend on whether other code has been hit before, etc. My understand of TestTools.UnitTesting is that whenever I run a set of unit tests, any within the same project run within the same process, thus any static state is maintained from test to test, whereas a Unit Test project boundary also implies a process boundary and thus, if I run 3 tests from project A then a fourth from project B, state is maintained from 1>2>3 (in whatever order they run) but then 4 is virgin and any static state is default.

所以现在我的问题是两个:

So now my questions are two:

1)我的评估是正确的:当在同一组中运行测试(全部运行或选择运行)时,单元测试项目与流程之间具有1:1的关系,还是我所缺少的细微差别?

1) is my assessment correct that a unit test projects have a 1:1 relationship with processes when tests are run in a group (run all or run selected), or is there more nuance there that I'm missing?

2)无论如何,如果我有一个测试肯定需要对其使用和测试的自定义对象进行全新的默认静态测试,那么与为其提供自己的测试项目相比,我有一个更优雅的选择来创建它吗?

2) Regardless, if I have a test that definitely needs fresh, default static state for the custom objects it uses and tests, do I have a more elegant option for creating it than giving it its own test project?

推荐答案

统计信息实际上不是每个进程,而是每个应用程序域(由AppDomain类表示).一个进程可以具有多个AppDomain.AppDomain具有自己的静态特性,可以为部分受信任的代码提供沙箱功能,并且可以卸载,从而允许在不重新启动应用程序的情况下对同一程序集的较新版本进行热插拔.

Statics are not actually per process, but per application domain, represented by the AppDomain class. A single process can have several AppDomains. AppDomains have their own statics, can provide sandboxing to partially trusted code, and can be unloaded allowing newer versions of the same assembly to be hot swapped without restarting the application.

您的测试运行程序可能会为每个测试程序集创建一个新的AppDomain,以便每个程序集都具有自己的静态变量.您可以创建一个AppDomain来即时执行相同操作.对于纯单元测试而言,这通常不是很好,但是我不得不使用粗鲁"的库来执行各种静态初始化和无法清除或重置的缓存.在这种集成方案中,它非常有用.

Your test runner is likely creating a new AppDomain per test assembly so each assembly gets its own static variables. You can create an AppDomain to do the same on the fly. This is not typically great for pure unit tests, but I've had to work with "rude" libraries that do all kinds of static initialization and caching that cannot be cleaned out or reset. In those sorts of integration scenarios it is very useful.

您可以使用此帮助程序来运行一个简单的委托:

You can use this helper to run a simple delegate:

public static class AppDomainHelper
{
    public static void Run(Action action)
    {
        var domain = AppDomain.CreateDomain("test domain");
        try
        {
            domain.DoCallBack(new CrossAppDomainDelegate(action));
        }
        finally
        {
            AppDomain.Unload(domain);
        }
    }
}

请注意,传递给 Run 的委托 action 不能具有任何捕获的变量(例如从lambda中获取).这是行不通的,因为编译器将生成一个不可序列化的隐藏类,因此它无法通过AppDomain边界.

One caution is that the delegate action passed to Run cannot have any captured variables (as in from a lambda). That doesn't work because the compiler will generate a hidden class that is not serializable and so it cannot pass through an AppDomain boundary.

这篇关于使用静态变量的单元测试C#/.NET类(单元测试过程隔离)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆