今天有同事给一个WPF程序的后台逻辑写UT,用的是NUnit框架,写之前感觉UI不好写UT,给后台逻辑写UT应该是没有什么问题,但是写开了才发现问题。
问题就出在了后台逻辑获取资源的部分,代码类似下面。
Application.Current.Resources[XXXX]
运行时抛出NullReferenceException,Application.Current为null。
很好理解,当前由于是用NUnit测试后台DLL,这时这个程序是基于WinForm的,而代码中要获得的是WPF Application,的确应该是null。这时才发现代码写得有问题——可测试性不好,但是代码已经冻结了,不是Fix bug不可以改。(这个时候才开始写UT,汗……)而这种代码在DLL中也不少。怎么办呢?
Application.Current是只读的,在UT里先启动原来的WPF程序?肯定不行的。只读其实不是问题,邪恶地想到了用反射给后面的变量直接赋值。得知道变量名啊,打开Reflector,发现变量名叫_appInstance,好在这时多想了一个问题,这个变量是什么时候被赋值的呢?第一感觉就是在个什么初始化的方法里,没找几个就发现就是在Appliction的构造函数里。
看来不用反射了。
在UT的Startup方法里加两行代码。
Application app = new Appliction(); //这个app,就是Application.Current
Application.Current.Resources = Application.LoadComponents(…);
完成,这样资源就可以被正常地访问到了。如果没看一下源代码,真要傻呼呼地用反射赋值了。