.net单元测试——解除依赖
最近在看.net单元测试艺术,我也喜欢单元测试,这里写一下如何在测试中解除对象间的依赖。
假如有这样的一个需求,当用户登陆时,我需要对用户名和密码进行验证,然后再将用户名写入日志中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
public
class
MyLogin { public
bool
Valid( string
userName, string
passWord) { var
isValid = userName == "admin"
&& passWord == "123456" ; WriteLog(userName); return
isValid; } private
void
WriteLog( string
message) { //....写入数据库或文件中 } } |
上面代码中,如果我们写单元测试时会发现,WriteLog方法依赖于文件或数据库时,这时测试会比较困难一些。首先我们需要对解除依赖,再进行测试。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 |
public
class
MyLogin { public
ILog Log { get ; set ; } public
bool
Valid( string
userName, string
passWord) { var
isValid = userName == "admin"
&& passWord == "123456" ; Log.Write(userName); return
isValid; } } public
interface
ILog { void
Write( string
message); } |
这时我们引入了ILog接口,在调用Valid方法前,需要对属于Log进行赋值,这里,我们便解除了对象之间的依赖。我们开始写单元测试,测试中,我们需要自己模拟一个桩对象。
桩对象是对系统中现有依赖项的一个替代品,可人为控制,通过使用桩对象,无需涉及依赖项,即可直接对代码进行测试。
测试框架这里我选用了NUnit框架。测试代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 |
[TestFixture] public
class
MyLoginTest { [Test] public
void
Vaild_Test() { MyLogin login = new
MyLogin(); login.Log = new
TestLog(); var
isLogin = login.Valid( "admin" , "123456" ); Assert.AreEqual(isLogin, true ); } } public
class
TestLog : ILog { public
void
Write( string
message) { //nothing } } |
这里我定义了一个类TestLog,这个类所生成的对象就是一个桩对象,桩对象的目的是为了替换测试中的依赖项,有些时候,依赖项可能需要文件或某些配置,导致很难测试,所以,为了方便测试,我们使用了桩对象。
上面的例子中,我们通过接口完成了对象间的依赖解除,再通过属性完成对接口的赋值,如果不使用属性,我们还可以用别的方法对接口进行赋值。
- 通过构造函数进行赋值。
1
2 |
public
MyLogin(ILog log) Log = log; |
在测试中,初始化Mylgoin对象时,把桩对象传给构造函数即可。
2. 通过工厂模式进行赋值。
通过工厂类来生成ILog对象,并且工厂类要允许传入ILog对象,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 |
public
class
MyLogin { public
bool
Valid( string
userName, string
passWord) { var
isValid = userName == "admin"
&& passWord == "123456" ; var
log = Factory.CreateLog(); log.Write(userName); return
isValid; } } public
interface
ILog { void
Write( string
message); } public
class
Factory { private
static
ILog iLog; public
static
ILog CreateLog() { return
iLog; } public
static
void
SetLog(ILog log) { iLog = log; } } |
测试类中,要对Factory的SetLog方法进行赋值,其它操作基本不变。
- 使用虚方法或IOC容器。
这些操作需要根据实际情况去使用。不要因为测试去改变你的设计(过度测试),除非你的设计无法测试。
总结: 对于开发人员来讲,单元测试是很重要一项工作。它会让你的代码结构更加清晰,代码的可读性也会更好。下一节,写一下如何使用框架进行测试,毕竟写桩对象还是要花很多时间的。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。