DotNet笔记--Unit Test With Fake
1 简单说一下DotNet Unit Test
Unit Test属于白盒测试的一种,直接针对代码进行测试,测试的单位往往是Method.如果测试的程序集没有其他的依赖引用,这种测试就很简单了,设置各种用例执行即可。但是,现实环境是复杂的,一个软件产品往往是由多层构成的,每个层往往分布于多个程序集中,这样导致的结果就是,为了获取来自其他层次的数据就很困难。举例来说,A的MethodA依赖于B中的MethodB,那么如何解除这种依赖呢?
微软给出了解决方案。
但是这种依赖又是分为两种情况的:1)B中的方法是基于接口的 2)B中的方法是没有接口的
针对这这两种情况,微软分别给出了Stub和Shim两种技术术语。但是很显然:1)我们自己生产的软件是鼓励进行接口编程的 2)对于第三方的库的输出往往是可以预计的。因此我们暂时先搞明白stub这种情况。
B中有接口,我们依赖于其中一个方法,那么进行分离的最朴素的想法就是我们自己实现其接口,然后由我们自己的实现返回那个接口,这样一种“Substitute”就解耦了:
这个技术有两个特点(依赖于程序集B,程序集的名称暂时成为Assembly.B):
1)在测试工程的referrence列表中找到Assembly.B,然后右键选择“Add Faske”,系统默认生成了Assembly.B.Fake这个冒牌货
2)实现其中的方法,在实现过程中构造我们的Fake数据
接口定义
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FakeTestLib { public interface CommonBaseIntf { Int32 SumTwoNum( Int32 i_firstPara, Int32 i_secPara ); Int32 Num { get; set; } } }
系统生成的Fake类型定义:
#region Assembly FakeTestLib.Fakes.dll, v1.0.0.0 // D:\PrivateCodePath\Rainy.Draft\TestWithFakeStub\FakesAssemblies\FakeTestLib.Fakes.dll #endregion using FakeTestLib; using Microsoft.QualityTools.Testing.Fakes; using Microsoft.QualityTools.Testing.Fakes.Stubs; using System; using System.Diagnostics; namespace FakeTestLib.Fakes { // Summary: // Stub type of FakeTestLib.CommonBaseIntf [DebuggerDisplay("Stub of CommonBaseIntf")] [DebuggerNonUserCode] [StubClass(typeof(CommonBaseIntf))] public class StubCommonBaseIntf : StubBase<CommonBaseIntf>, CommonBaseIntf { // Summary: // Sets the stub of CommonBaseIntf.get_Num() public FakesDelegates.Func<int> NumGet; // // Summary: // Sets the stub of CommonBaseIntf.set_Num(Int32 value) public FakesDelegates.Action<int> NumSetInt32; // // Summary: // Sets the stub of CommonBaseIntf.SumTwoNum(Int32 i_firstPara, Int32 i_secPara) public FakesDelegates.Func<int, int, int> SumTwoNumInt32Int32; // Summary: // Initializes a new instance of type StubCommonBaseIntf public StubCommonBaseIntf(); // Summary: // Attaches delegates to emulate StubCommonBaseIntf.Num as a property with a // backing field. public void AttachBackingFieldToNum(); } }
测试实现:
public void TestSumTwoNum() { var baseIntf = new FakeTestLib.Fakes.StubCommonBaseIntf() { SumTwoNumInt32Int32 = (first, sec) => { var result = 0; checked { result = 200; } return result; }, }; Assert.IsTrue(baseIntf is CommonBaseIntf); Assert.AreEqual(200, baseIntf.SumTwoNumInt32Int32(10, 190)); }