术语
Tested Object –
被测对象
Mock –
假的
or
仿制的对象
What is Mock Object?
在讨论中我大致了解到
Mock Object
一般是用来做辅助单元测试,它负责隔离
Tested Object
与真实环境中模块或实体
(Real world object)
的交互,并“替代”
or “
冒充
”
这些真实模块或实体与
Tested Object
进行交互。
在“
JUnit in action
”这本书中关于
Mock Object
的描述如下:
A
mock object (or mock for short) is an object created to stand in for an
object that your code will be collaborating with. Your code can call
methods on the mock object, which will deliver results as set up by your
tests.
Mock Object
给我带来什么好处?
看看下面的图:
|-----------------------------------------------------------------|
|
|
|
|---------------------|
|
|-----------------------------|
|
|
Tested
|
<------------------------------------------
à
| External Mock Object |
|
|
Object
|
|
|----------------------------|
|
|---------------------|
|
|
/|\
|--------------------|
|
|
|-------
〉
|
Internal Mock
|
|
|
|
Object
|
|
|
|--------------------|
|
|
[Your system scope]
|
|--------------------------------------------------------- --------
|
在测试你的
Tested Object
时,你可能会与你系统内的某个模块或系统外某个实体交互,而这些模块或实体在你做单元测试的时候可能并不存在,这时:
Ø
Internal Mock Object
可能是一个你的系统尚未完成的模块的“替身”
(replacement)
;
Ø
External Mock Object
可能是测试你的
Tested Object
时需要的外部的环境实体的“替身”(
replacement
)。
不知道这样给
Mock Object
分类是否正确
J
我们来看看与
Real world object
交互有什么不足之处:
Ø
Real world object
的行为具有不确定性,我们难于控制它们的输出
or
返回结果。
Ø
Real world object
有些时候是难于被建立的或者说是无法获得的。
Ø
Real world object
的有些行为难于被触发,如磁盘已满,网络
error
等。
Ø
Real world object
可能不存在,比如你的
Tested Object
需要与你的系统的另一个
module
交互,而另一个
module
尚未开发完毕。
当然还不止这些,我们仅仅是列出一部分。
使用
Mock Object
替代
Real world object
后我们就会解决上述问题,换句话说当上面的情况出现后,我们就可以使用
Mock Object
。这也是什么时候该使用
Mock Object
的
answer
。
Mock Object
是我们自己编写的,我们拥有控制它的绝对的权力,我们可以定制它的行为和输出。
Use Mock Object
使用
Mock Object
解决上述问题可分三步走:
1. Use an interface to describe the object
2. Implement the interface for production code
3. Implement the interface in a mock object for testing [3]
还有一点就是对于
Internal Mock Object
早晚你要实现出其
Real world object
的,因为那是你系统的一部分。
一个改自资料
[3]
的例子
public interface Environmental {
public long getTime();
// Other methods omitted...
}
对于这样一个接口,我们提供两种实现
,
//real world object
public class SystemEnvironment implements Environmental {
public long getTime() {
return System.currentTimeMillis();
}
// other methods ...
}
//mock object
public class MockSystemEnvironment implements Environmental {
public long getTime() {
return currentTime;
}
public void setTime(Time aTime){
this.currentTime = aTime;
}
private Time currentTime;
//others
}
我们可以看到在
MockSystemEnvironment
中我们提供“
setTime
”函数是为了提供控制
Mock Object
的接口。
我们要测试的类
//TestedObject
public class TestedObject{
private Environmental env;
TestedObject(Environmental aEnv){
this.env = aEnv;
}
public boolean isAm(){
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(env.getTime());
int
hour = cal.get(Calendar.HOUR_OF_DAY);
if (hour <=12) return true;
return false;
}
}
将要测试的类放入单元测试框架
public class
TestTestedObject extends
TestCase {
public void
testIsAm(){
MockSystemEnvironment env = new
MockSystemEnvironment();
// Set up a target test time
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2004);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 16);
cal.set(Calendar.MINUTE, 55);
long
t1 = cal.getTimeInMillis();
env.setTime(t1);
TestedObject to = new TestedObject(env);
assertFalse(to.isAm());
}
}
在该单元测试中我们使用了
Mock Object,
并且在使用前我们利用
setTime
接口,输入了我们需要的值。结果我们会通过测试。如果我们使用
Real Object
,我们得到的测试结果将是不固定的,后者可不是所期望的。从这个例子中你也应该体会到
Mock object
的一些好处了。
如果我们总是手动写我们需要的
Mock Object
,那将是一个很大的工作量。现在业界有了
Mock Objects
、
easy mock
等开源框架的支持,是我们编写
Mock object
变得越来越容易。
参考资料:
1
、《
Test-Driven Development – A practical guide
》
2
、《
JUnit in action
》
3
、《
Pragmatic Unit Testing
》
分享到:
相关推荐
概述我最初编写 MockObject 是为了帮助我对使用 COM 对象连接到硬件设备的代码进行单元测试。 通过交换实际 COM 对象的模拟,我可以模拟我想要的任何设备行为。 从那以后,我也用它来模拟 HTTP 会话,而且无论您想...
当我们处理一个类需要实现多个接口的情况时,可以创建多个Mock对象分别模拟每个接口,并将它们传递给测试对象。在上面的例子中,`MyClass`依赖于`IService1`和`IService2`,我们创建了两个独立的Mock对象,分别模拟...
4. **验证模式(Verify State)**:测试结束后,调用`EasyMock.verify(mockObject)`检查模拟对象的行为是否符合预期。 5. **扩展EasyMock**:EasyMock还可以与其它库结合,如`EasyMock.ClassExtender`用于创建扩展...
1. 模拟对象(Mock Object):模拟对象是真实对象的替代品,它可以预定义行为和返回值,以便在测试中控制依赖对象的行为。 2. 验证(Verification):验证是检查模拟对象在测试期间是否按照预期执行了某些操作,如...
1. **Mock Objects**:OCMock 可以生成模拟对象(mock object),这些对象可以模仿真实对象的方法调用并记录这些调用。在测试中,我们可以预设模拟对象如何响应特定的方法调用,包括返回特定的值或引发异常。这样,...
Mock Object是一种在单元测试中模拟真实对象的行为和交互的技术,它允许测试人员控制对象间的依赖关系,从而在隔离环境中测试单个组件。这样可以避免复杂的真实系统依赖,提高测试的效率和准确性。 首先,Eclipse是...
在C++中,你可以使用`NiceMock`、`StrictMock`和`MockObject`来创建不同类型的模拟对象。`NiceMock`默认对未指定的调用采取宽容态度,而`StrictMock`则要求所有调用都必须预先设置。`MockObject`允许自定义行为。 ...
Mock对象是软件测试中的一种重要工具,用于模拟真实对象的行为,从而在单元测试中隔离被测代码的依赖项。本项目将介绍如何使用Objective-C的测试框架和第三方库来创建和使用Mock对象,并提供一些示例代码。 **适用...
`Mock`是创建模拟对象的基础,它会返回一个没有预先定义行为的全新Mock对象。你可以通过设置`return_value`属性来决定调用Mock对象时返回什么,通过`side_effect`属性指定调用时发生的副作用。 `patch`和`patch....
"mock-object"项目可能是这样的一个库,它简化了在JavaScript中创建和管理模拟对象的过程,使开发者能够更轻松地进行测试驱动开发(TDD)。 在测试中,模拟对象通常用于以下几个目的: 1. **隔离依赖**:当我们...
`createMock()`方法接收一个类名作为参数,返回一个`MockObject`,这个对象的行为可以根据测试需求进行定制。 例如,在测试`PostFactory`时,如果`PostFactory`依赖于`Post`类,我们可以通过`createMock(Post::...
它提供了多种类型的 Mock 对象,可以模拟不同类型的行为,帮助开发者更好地测试自己的代码。 二、基本对象 Mockpp 提供了多种类型的基本对象,包括 ExpectationValue、ExpectationList、ConstraintList、...
Mock对象是模拟真实对象的行为和状态,以便在测试过程中隔离被测试代码,确保测试的精确性和可控性。VBMock是一个针对Visual Basic编程环境的Mock对象生成工具,它的开源特性使得开发者可以自由地使用、修改和分享这...
在Python的单元测试中,Mock是一个非常重要的工具,它允许我们模拟对象的行为,以便在测试过程中隔离被测试代码与其他系统的交互。Mock可以帮助我们避免在测试时产生不必要的副作用,提高测试速度和效率。以下是对...
EasyMock 是一个用于生成模拟对象(Mock Object)的类库,主要用于单元测试。它提供了一种简单的方法来模拟接口或类的行为,使得在测试中可以模拟真实环境中的对象。 EasyMock 的主要特点包括: 简单易用:使用 ...
为了进行有效的单元测试,经常会用到模拟对象(mock objects),这就是 GMock 的作用所在。GMock 是 Google 推出的一款强大的 C++ 测试框架 Google Test(GTest)的一部分,但在这里我们讨论的是它在 Groovy 语言...
6. **清理**:最后,使用`mockObject.Replay()`和`mockObject.Verify()`方法来切换到验证模式,并在测试结束时清理模拟对象。 Numock还支持其他高级特性,如约束条件、期望顺序和部分模拟。例如,你可以指定方法...
在软件开发中,Mock是一种用于模拟对象行为的技术。它允许开发者创建一个模拟的对象来代替实际的对象,这样可以在不依赖实际对象的情况下对某个组件或模块进行测试。通过Mock,我们可以控制返回值、抛出异常等行为,...
3. 定义模拟行为:通过 `context.mock(Class<T> type)` 方法创建模拟对象,并通过 `when(mockObject).method()` 定义其方法的行为。例如: ```java MyNonInterfaceClass mockMyClass = context.mock...