yun9420yun tian yao微信能查出来这个微信号的地址吗

开始使用Mockito -- 使用Mockito和JUnit【一】 -
- ITeye技术网站
博客分类:
一段常见的代码
单元测试是项目的重要组成部分。尤其是对持续发展的产品,单元测试在后期的维护,回归有重要等方面有重要作用。
这样代码在项目中随处可见,看看我们应该如何测试
public class NotifyService {
private UserC
private MessageC
public void sendMessage(long userId, String message) {
String email = uc.getUser(userId).getEmail();
mc.sendEmail(email, message);
public void setUc(UserCenter uc) {
public void setMc(MessageCenter mc) {
UserCenter和MessageCenter都是接口,User是一个简单的JavaBean
由于uc和mc乃外部依赖,此类不需也不应保证uc和mc的正确性,此类只需保证:
假设uc和mc是正确的,那么我也是正确的。
所以需要隔离依赖--使用mock
使用EasyMock
如果使用EasyMock,此类之单元测试或许如下[需要static import org.easymock.EasyMock类的相关方法]
public class EasyMockNotifyServiceTest {
private NotifyService notifyS
private UserC
private MessageC
public void setUp() {
notifyService = new NotifyService();
uc = createMock(UserCenter.class);
mc = createMock(MessageCenter.class);
notifyService.setUc(uc);
notifyService.setMc(mc);
public void testSendMessage() {
Long id = 1L;
String email = "foo@bar";
String message = "hello";
expect(uc.getUser(id)).andReturn(createUserWithEmail(email));
mc.sendEmail(eq(email), eq(message));
replay(uc);
replay(mc);
notifyService.sendMessage(id, message);
verify(mc);//verify a mocked behavior
private User createUserWithEmail(String email) {
User user = new User();
user.setEmail(email);
当然,此测试并不充分,easymock需要mock每个依赖,对mock的所有方法调用作expect,然后验证需要验证的行为。
mc.sendEmail(eq(email), eq(message));
此处代码理解起来有些怪异,实际上,此处的语义应该是 expect mc.sendEmail... called,即方法执行完毕后sendMail必以正确的参数调用,奈何java 泛型中并未覆盖void型,所以通常会在mock行为调用之后
加上此行以明确语义
expectLastCall().times(1);
另外一个值得注意的地方
verify(mc);//verify a mocked behavior
并未验证uc,我的想法是对于uc我们需要它提供数据(桩),而不需要验证其行为。
使用Mockito
假使使用Mockito,单元测试也许是这个样子的[需要static import org.mockito.Mockito类的相关方法]
public class NotifyServiceTest {
private NotifyService notifyS
private UserC
private MessageC
public void setUp() {
notifyService = new NotifyService();
uc = mock(UserCenter.class);
mc = mock(MessageCenter.class);
notifyService.setUc(uc);
notifyService.setMc(mc);
public void testSendMessage() {
long userId = 1L;
String email = "foo@bar";
when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
notifyService.sendMessage(userId, "hello");
verify(mc).sendEmail(eq(email), eq("hello"));
private User createUserWithEmail(String email) {
User user = new User();
user.setEmail(email);
看到testSendMessage方法
public void testSendMessage() {
long userId = 1L;
String email = "foo@bar";
when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
notifyService.sendMessage(userId, "hello");
verify(mc).sendEmail(eq(email), eq("hello"));
语义不言自明
测试前,从uc获得email
测试后,必须调用mc.sendEmail,所以验证之
通过一个简单的例子,可以看到:mockito在使我们的测试代码更直接,语义更明确
浏览 22102
浏览: 58788 次
来自: 杭州
chenjingbo 写道尼玛,看不懂啊大湿年轻时候胡乱瞎写的 ...
尼玛,看不懂啊大湿
试试引用M-x json-pretty-print-buffe ...
学习了。。,
xing_kenny 写道需要增加 @Before publi ...单元测试中mock的使用及mock神器jmockit实践 - 测试&开发 技术 - ITeye技术网站
博客分类:
在最近的r应用的单元测试中,经常需要用到mock,可以说mock在ut (unit test)中是无处不在的。而在r的ut实践中也找到了一种很简洁的mock方式,不仅解决了ut中所有需要mock的地方,而且可以很少量的代码来完成mock。详见下文。
一.Mock的使用场景:
比如以下场景:
1. mock掉外部依赖的应用的HSF service的调用,比如uic,tp 的hsf服务依赖。
2. 对DAO层(访问mysql、oracle、tair、tfs等底层存储)的调用mock等。
3. 对系统间异步交互notify消息的mock。
4. 对method_A里面调用到的method_B 的mock 。
5. 对一些应用里面自己的 class(abstract, final, static),interface,annotation ,enum,native等的mock。
二. Mock工具的原理:
mock工具工作的原理大都如下:
1. record阶段:录制期望。也可以理解为数据准备阶段。创建依赖的class 或interface或method ,模拟返回的数据,及调用的次数等。
2. replay阶段:通过调用被测代码,执行测试。期间会invoke 到 第一阶段record的mock对象或方法。
3. verify阶段:验证。可以验证调用返回是否正确。及mock的方法调用次数,顺序等。
三. 当前的一些Mock工具的比较:
历史曾经或当前比较流行的Mock工具有EasyMock、jMock、Mockito、Unitils Mock、PowerMock、jmockit等工具。
他们的功能对比如下:
来源:/p/jmockit/
从这里可以看到,当前为什么jmockit为什么这么火爆了!所以我们的UT中的mock工具也选择了目前无所不能的jmockit。
而在使用的过程中,感觉到jmockit的 Auto-injection of mocks 及 Special fields for "any" argument matching
及各种有用的 Annotation 给测试代码精简和测试效率提升带来了实实在在的好处。
四. Jmockit的简介:
JMockit 是用以帮助开发人员编写测试程序的一组工具和API,它(/p/jmockit/)完全基于 Java 5 SE 的 java.lang.instrument 包开发,内部使用 ASM 库来修改Java的Bytecode。正是由于基于instrument,可以修改字节码。所以这也是它强大的原因。
Jmockit可以mock的种类包含了:1.class(abstract, final, static) ;2.interface ;3.enum ;4.annotation ;5.native 。
Jmockit 有两种mock的方式:
1. Behavior-oriented(Expectations & Verifications)
2. State-oriented(MockUp&GenericType&)
通俗点讲,Behavior-oriented是基于行为的mock,对mock目标代码的行为进行模仿,更像黑盒测试。State-oriented 是基于状态的mock,是站在目标测试代码内部的。可以对传入的参数进行检查、匹配,才返回某些结果,类似白盒。而State-oriented的 new MockUp基本上可以mock任何代码或逻辑。非常强大。
以下是jmockit的APIs和tools:
可以看到jmockit常用的Expectation、NonStrictExpectations 期望录制 及Annotation @Tested、@Mocked,@NonStrict、@Injectable 等简洁的mock代码风格。而且jmockit 还自带了code coverage的工具供本地UT时候看逻辑覆盖或代码覆盖率使用。
五.Jmockit的实践:
第一步:添加jmockit的jar包依赖
在refund的单元测试过程中,第一步:应用pom中引入jmockit的jar包,可以顺带引入jmockit自带的code coverage的jar。
第二步:一个完整的Jmockit的示例:
这个是对rr里面查询金额范围 queryeRange的单元测试。通过看被测代码可以看到这个方法的实现里面调用了
feeultDO = cosService.queryCodFee(delId);
这个外部的hsf依赖 获取了feeultDO 。
这个hsf调用是需要mock的。
传统的mock或ut ,对 confirmGoodsService 这个bean是需要初始化,通过spring的配置,初始化加载等 一大堆代码。
jmockit通过了注解的方式:
@Injectable
private Co
一个Annotation就搞定了所有的配置,加载等问题。直接复用开发代码里面的bean,节省了大量的代码。
另外 @Tested
ReferImpl reerImpl = new RImpl();
这里也用到了注解 @Tested
表示被测试的class 。
另外还有常用的注解:@Mocked,@NonStrict等。
而这段代码就是mock的核心:录制被mock的method的行为及期望返回:
new Expectations(){
coce.quendFee(anyLong);
times = 1;
可以返回任意需要的测试类型;
表示期望被调用的次数。
是不是看起来非常简洁明了。
而上面该段代码如果 换成基于状态的mockup 代码如下:
&图片省略&
采用MockUp的方式,可以mock任意的mock对象或方法,因为它直接改写了原method的实现逻辑,直接返回需要的数据。
这也是jmockit彪悍的地方之一。
最后数据回收,防止各个testcase的mock相互影响的方式:
Mockit.tearDownMocks();
这一步也可以省略。
还要重点介绍的就是mock期望里面的入参 any。
这个any系列的万能入参类型,也可以节省很多mock代码,可以高效的准备任何入参类型。
以上,一个最简单的,也最实用的jmockit的示例。
jmockit的更多,对interface及method的单元测试的示例,将在后续总结汇总。
六、 Jmockit自带的code coverage :
工程的 pom文件中引入 jmockit-coverage 后,本地eclipse启动单元测试后, 会自动统计单元测试的代码覆盖率。关于行覆盖,方法覆盖,类覆盖,分支逻辑覆盖等各种数据都可以看到。
IDE启动UT时候,加载 code coverage
&图片省略&
点击进去,可以看到具体的覆盖逻辑:
&图片省略&
其中绿色部分表示源代码被run过。
代码覆盖对指导单元测试的测试逻辑,覆盖等提供了直观的指示。
(转载请注明出处:
以上,就是在单元测试中mock技术的应用:Jmockit的使用介绍及实际应用示例。它在单元测试中确实可以很少的代码mock掉外部依赖,提高ut的效率,并且 自带的code coverage可很方便的看到ut对被测代码的覆盖效果,指导测试设计。
浏览: 21904 次
来自: 杭州
/blog/21 ...使用Mockito对异步方法进行单元测试 - 推酷
使用Mockito对异步方法进行单元测试
之前我拍着胸脯承诺要维护的我博客,因此才有了这篇文章。但是请忘记我的那些承诺,我今天要写的是关于
,这是一个当你写单元测试时经常会用到的对象Mock框架。
这篇文章假设你已经知道了什么是
以及为什么你要写单元测试。另外,我强烈建议你阅读
常见的场景
有些时候我们需要测试有回调的函数,这意味着它们是异步执行的。这些方法测试起来并不那么容易,使用
Thread.sleep(milliseconds)
来等待它们执行完成只能说是一种蹩脚的实现,并且会让你的测试具有不确定性。那么我们如何来对异步函数进行测试呢?
拯救了我们!
翠花,上示例
假设我们有一个实现了
DummyCallback
DummyCaller
DummyCaller
doSomethingAsynchronously()
函数,该函数会调用
DummyCollaborator
doSomethingAsynchronously(DummyCallback callback)
函数,在调用该函数时将这个callback参数设置为该
DummyCaller
doSomethingAsynchronously(DummyCallback callback)
的任务在后台线程中执行完成之后就会回调这个callback。
还是直接看代码会更容易理解 :
DummyCallback接口 :
public interface DummyCallback {
public void onSuccess(List&String& result);
public void onFail(int code);
DummyCaller类 :
public class DummyCaller implements DummyCallback {
// 执行异步操作的代理类
private final DummyCollaborator dummyC
// 执行结果
private List&String& result = new ArrayList&String&();
public DummyCaller(DummyCollaborator dummyCollaborator) {
this.dummyCollaborator = dummyC
public void doSomethingAsynchronously() {
dummyCollaborator.doSomethingAsynchronously(this);
public List&String& getResult() {
return this.
public void onSuccess(List&String& result) {
this.result =
System.out.println(&On success&);
public void onFail(int code) {
System.out.println(&On Fail&);
真正的异步执行操作的DummyCollaborator类。
public class DummyCollaborator {
public static int ERROR_CODE = 1;
public DummyCollaborator() {
public void doSomethingAsynchronously (final DummyCallback callback) {
new Thread(new Runnable() {
public void run() {
Thread.sleep(5000);
callback.onSuccess(Collections.EMPTY_LIST);
} catch (InterruptedException e) {
callback.onFail(ERROR_CODE);
e.printStackTrace();
}).start();
创建我们的测试类
我们有2种不同的选择来测试我们的异步函数,但是首先我们先创建一个DummyCollaboratorCallerTest测试类。
public class DummyCollaboratorCallerTest {
// 要测试的类型
private DummyCaller dummyC
private DummyCollaborator mockDummyC
private ArgumentCaptor&DummyCallback& dummyCallbackArgumentC
public void setUp() {
MockitoAnnotations.initMocks(this);
dummyCaller = new DummyCaller(mockDummyCollaborator);
在setup函数中我们使用MockitoAnotations来初始化 Mock和ArgumentCaptor,我们暂时还不需要关心它们。
在这里我们需要关心的是在测试执行之前初始化了Mock对象和被测试的类,这些初始化代码都在setup中。记住,所有要测试的函数都要被测试两次。
让我们来看看下面的两种测试方案。
为我们的回调设置一个Anwser
这是我们使用
doAnswer()
来为一个函数进行打桩以测试异步函数的测试用例。这意味着我们需要理解返回一个回调(同步的),当被测试的方法被调用时我们生成了一个通用的anwser,这个回调会被执行。
最后,我们调用了doSomethingAsynchronously函数,并且验证了状态和交互结果。
public void testDoSomethingAsynchronouslyUsingDoAnswer() {
final List&String& results = Arrays.asList(&One&, &Two&, &Three&);
// 为callback执行一个同步anwser
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
((DummyCallback)invocation.getArguments()[0]).onSuccess(results);
}).when(mockDummyCollaborator).doSomethingAsynchronously(
any(DummyCallback.class));
// 调用被测试的函数
dummyCaller.doSomethingAsynchronously();
// 验证状态与结果
verify(mockDummyCollaborator, times(1)).doSomethingAsynchronously(
any(DummyCallback.class));
assertThat(dummyCaller.getResult(), is(equalTo(results)));
[译者注 : 在doAnswer函数中当调用mockDummyCollaborator对象的doSomethingAsynchronously (final DummyCallback callback)函数时会触发Answer匿名内部类的answer(InvocationOnMock invocation)函数]
使用ArgumentCaptor
第二种实现是使用ArgumentCaptor。在这里我们的callback是异步的: 我们通过ArgumentCaptor捕获传递到DummyCollaborator对象的DummyCallback回调。
最终,我们可以在测试函数级别进行所有验证,当我们想验证状态和交互结果时可以调用
onSuccess()
public void testDoSomethingAsynchronouslyUsingArgumentCaptor() {
// 调用要被测试发函数
dummyCaller.doSomethingAsynchronously();
final List&String& results = Arrays.asList(&One&, &Two&, &Three&);
// Let's call the callback. ArgumentCaptor.capture() works like a matcher.
verify(mockDummyCollaborator, times(1)).doSomethingAsynchronously(
dummyCallbackArgumentCaptor.capture());
// 在执行回调之前验证结果
assertThat(dummyCaller.getResult().isEmpty(), is(true));
// 调用回调的onSuccess函数
dummyCallbackArgumentCaptor.getValue().onSuccess(results);
// 再次验证结果
assertThat(dummyCaller.getResult(), is(equalTo(results)));
两种实现的主要的不同点是当使用
方案时我们创建了一个匿名内部类,并且将它的元素从
invocation.getArguments()[n]
转换到我们需要的类型,但是万一我们修改了我们的参数类型,那么这个测试就会’fail fast’。另一方面,当我们使用
时我们可能能够更精细的控制测试用例,因为我们能在测试用例中手动调用回调对象。
面对这两种方案,有时候我们不知道作何选择,但是不用担心,因为这是一个常见的问题。以我们的经验来看,同时使用这两种方案来测试异步函数会是一个更可靠的途径。
我希望这篇文章对你有用,另外,请记住,欢迎给这篇文章的反馈,或许还有更好的实现。当然,如果你有任何的疑问也可以联系我。
。这些代码都是关于Java和Android的,因为我们在几个月前做了一场相关的演讲。
我强烈建议你阅读
以对这个框架有更深入的了解,这份文档非常清晰,并且有非常棒的示例!
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致使用Mockito进行单元测试【2】—— stub 和 高级特性 - qiuguo0205's blog - ITeye技术网站
博客分类:
一篇中介绍了Mockito的基本信息,现在接着介绍Mockito强大的stub功能
2. Mockito使用实例
5. 对连续的调用进行不同的返回 (iterator-style stubbing)
还记得在实例2中说道当我们连续两次为同一个方法使用stub的时候,他只会使用最新的一次。但是在某一个方法中我们确实有很多的调用怎么办呢?mockito当然想到这一点了:
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
//First call: throws runtime exception:
mock.someMethod("some arg");
//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));
//Any consecutive call: prints "foo" as well (last stubbing wins).
System.out.println(mock.someMethod("some arg"));
当然我们也可以将第一句写的更简单一些:
when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three");
参见网页例子10。
6. 使用回调进行stub【Stubbing with callbacks】
我们可以使用generic的Answer接口来让mock对象执行我们期望它执行的内容。比如我们可以查看调用方法的参数信息,并根据这个信息进行不同的处理,这可以使我们的stub变得十分的灵活。
when(mock.someMethod(anyString())).thenAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Object mock = invocation.getMock();
return "called with arguments: " +
//Following prints "called with arguments: foo"
System.out.println(mock.someMethod("foo"));
参见网页例子11。
7. 使用 doThrow()|doAnswer()|doNothing()|doReturn() 来 stub void方法
void方法也需要stub?呵呵,实际生活中我们应该只会用到doThrow来模拟这个void方法出错的情况吧,anyway,mockito提供了四个方法,发挥你的想象力吧:-)
doThrow(new RuntimeException()).when(mockedList).clear();
//following throws RuntimeException:
mockedList.clear();
参见网页例子12。
8. 在真实的对象上进行spy
spy的意思是你可以修改某个真实对象的某些方法的行为特征,而不改变他的基本行为特征,这种策略的使用跟AOP有点类似。下面举一个例子来说明:
List list = new LinkedList();
List spy = spy(list);
//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
//using the spy calls &b&real&/b& methods
spy.add("one");
spy.add("two");
//prints "one" - the first element of a list
System.out.println(spy.get(0));
//size() method was stubbed - 100 is printed
System.out.println(spy.size());
//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");
可以看到spy保留了list的大部分功能,只是将它的size方法改写了。不过spy在使用的时候有很多地方需要注意,一不小心就会导致问题,所以不到万不得已还是不要用spy。下面介绍两个spy的陷阱:
【1】有时我们无法使用when的方式来spy,此时我们就需要使用doReturn|Answer|Throw() 等方式来进行spy了:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
比如我们使用when的时候实际已经调用了get(0)方法,这个时候将直接抛出异常,所以此时应该使用doReturn来进行spy
【2】spy实际上是对对象做了一个拷贝,就像上面的,如果我们直接看list这个对象,它实际上只执行了这样一句话List list = new LinkedList();
【3】 无法spy final方法。
参见网页例子13。
9. 其他高级特性
当说到高级特性,我们就是说那些基本用不到,但是当我们想用的时候就非常顺手的功能,比如:
# 改变没有stub方法的默认返回值
网页例子14
# 抓取参数进行assert验证
网页例子15
# 重置mock对象
网页例子16
由于浙西而使用机会比较小,这里就不详述了,更多的例子还是参考网页吧
不知看了以上的内容,你是否觉得Mockito是使用mock进行单元测试的理想工具,如果是的话,就猛击
的主页下载并使用吧:-)
qiuguo0205
浏览: 159805 次
来自: 北京
XML配置的方式非常灵活,不过对于新手来说有点困难。我专门写了 ...
XML配置的方式非常灵活,不过对于新手来说有点困难。我专门写了 ...
你好我在官方上下不了这个代码,你能给我发一份吗还有就是这个是开 ...
应该可以这么理解,maven中java.home是jre的路径 ...本文由&– Sandbox Wang原创翻译,转载请看清文末的转载要求,欢迎参与我们的!
在过去的职业生涯里,我经常发现有些人不写测试代码,而他们声称不写的理由是无法轻易地写出覆盖多个不同模块的测试用例。好吧,我相信他们中的大部分要么是缺乏一些比较易掌握的技术手段,要么就是没时间来把它搞清楚,毕竟工作中总会有进度之类的各种压力。因为不知道该如何测试,所以就经常忽略集成测试,由此带来的问题就是越来越糟糕的软件、越来越多的BUG和更加失望的客户。所以我想分享一些个人的经验,揭开集成测试神秘的面纱。
如何对基于Spring的工程更好地进行集成测试
使用工具: Spring, JUnit, Mockito
想象有这样一个Spring工程,它集成了一些外部服务,例如,一些银行的web服务。那么,为这个工程写测试用例以及在持续集成系统中完成这些测试时所遇到的问题基本都差不多:
每次测试都会有交易进行,每次交易都需要付出金钱成本,这些成本最终由客户承担;
测试时发出的过多的请求有可能被认为是恶意请求,可能造成在银行的账户被封,后果是测试失败;
当使用非生产环境进行测试时,测试结果并不十分可靠,同样,后果是测试失败。
通常情况下,你对单个类进行测试的时候,问题很容易解决,因为你可以虚拟一些外部服务来供调用。但是当对整个巨大的业务流程进行测试的时候,意味你需要对多个部件进行测试,这时,需要你将这些部件都纳入到Spring容器中进行管理。所幸,Spring包含了非常优秀的,允许你将来自生产环境配置文件中的bean注入到测试环境中,但是对那些被调用的外部服务,需要我们自己去写模拟实现。一般人第一反应可能是在测试的setUp阶段对由Spring注入的bean进行重新注入(修改),但是这种方法需要再仔细考虑一下。
警告:通过这种方式,你的测试代码打破了容器自身的行为,所以没法保证在真实的环境中也如你测试的结果一样。
事实上,我们无需先实现模拟类然后再把它重新注入到所需的bean中,我们可以让Spring帮助我们一开始就注入模拟类。让我们用代码演示一下。
示例工程包含一个名为BankService的类,代表调用的外部服务,一个名为UserBalanceService的类,它会调用BankService。UserBalanceService实现的非常简单,仅仅完成将余额从String向Double类型的转换。
BankService.java的源码:
public interface BankService {
String getBalanceByEmail(String email);
BankServiceImpl.java的源码:
public class BankServiceImpl implements BankService {
public String getBalanceByEmail(String email) {
throw new UnsupportedOperationException("Operation failed due to external exception");
UserBalanceService.java的源码:
interface UserBalanceService {
Double getAccountBalance(String email);
UserBalanceServiceImpl.java的源码:
public class UserBalanceServiceImpl implements UserBalanceService {
@Autowired
private BankService bankS
public Double getAccountBalance(String email) {
return Double.valueOf(bankService.getBalanceByEmail(email));
然后是Spring的XML配置文件,添加所需要的bean声明。
applicationContext.xml的源代码:
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"&
&bean id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankServiceImpl"/&
&bean id="userBalanceService" class="ua.eshepelyuk.blog.springtest.springockito.UserBalanceServiceImpl"/&
下面是测试类UserBalanceServiceImplTest.java的源代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplProfileTest {
@Autowired
private UserBalanceService userBalanceS
@Autowired
private BankService bankS
public void shouldReturnMockedBalance() {
Double balance = userBalanceService.getAccountBalance("");
assertEquals(balance, Double.valueOf(123.45D));
如我们预料的一样,测试方法报UnsupportedOperationException异常。我们现在的目的是把BankService换成我们的模拟实现。直接使用Mockito来生成factory bean的方法是没问题的,但是有更好的选择,使用。继续之前可以先大概了解一下。
剩下的问题就简单了:如何让Spring注入模拟的bean而不是真实的bean,在Spring 3.1版之前除了新建一个XML配置文件之外没有其他的方法。但是自从Spring引入了之后,我们有了更加优雅的解决方式,虽然这种方式也需要一个额外的专门用作测试的XML配置文件。下面是这个用来测试的配置文件testApplicationContext.xml的代码:
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mockito="http://www.mockito.org/spring/mockito"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.mockito.org/spring/mockito https://bitbucket.org/kubek2k/springockito/raw/tip/springockito/src/main/resources/spring/mockito.xsd"&
&import resource="classpath:/springtest/springockito/applicationContext.xml"/&
&beans profile="springTest"&
&mockito:mock id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankService"/&
做相应修改过之后的测试类UserBalanceServiceImplProfileTest.java的源代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/testApplicationContext.xml")
@ActiveProfiles(profiles = {"springTest"})
public class UserBalanceServiceImplProfileTest {
@Autowired
private UserBalanceService userBalanceS
@Autowired
private BankService bankS
public void setUp() throws Exception {
Mockito.when(bankService.getBalanceByEmail("")).thenReturn(String.valueOf(123.45D));
public void shouldReturnMockedBalance() {
Double balance = userBalanceService.getAccountBalance("");
assertEquals(balance, Double.valueOf(123.45D));
你可能注意到了,在setUp方法里,我们定义了模拟的行为,并且在类上面加了@Profile的注解。这个注解激活了名为springTest的profile,因此使用Springockito模拟的bean就可以自动注入到任何它所需要的地方了。这个测试的运行结果会成功,因为Spring注入了Springockito 所模拟的版本,而不是applicationContext.xml里所声明的版本。
继续优化我们的测试
如果我们能将解决这个问题的方法更加推进一步的话,这篇文章看起来才没有缺憾。Springockito提供了另外一个名字叫作
的框架,它允许我们在测试类中使用注解来注入模拟类。继续看下去之前,您最好先去网站上大概瞧瞧。好了,下面是经过修改后的测试代码。
UserBalanceServiceImplAnnotationTest.java的源代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class,
locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplAnnotationTest {
@Autowired
private UserBalanceService userBalanceS
@Autowired
@ReplaceWithMock
private BankService bankS
public void setUp() throws Exception {
Mockito.when(bankService.getBalanceByEmail("")).thenReturn(String.valueOf(valueOf(123.45D)));
public void shouldReturnMockedBalance() {
Double balance = userBalanceService.getAccountBalance("");
assertEquals(balance, valueOf(123.45D));
请注意,这里并没有新引入的XML配置文件,而是直接使用了正式环境的applicationContext.xml。我们使用@ReplaceWithMock这个注解标记了类型为BankService的bean,而后在setUp方法中对模拟类的行为进行了定义。
Springockito-annotations项目有个巨大的优点,那就是,它使我们的测试代码建立在依赖覆盖的基础之上,通过这样,我们既不需要定义额外的XML配置文件,也不需要为了测试而去改动生产环境的配置文件。如果不使用Springockito-annotations的话,我们除了定义额外的XML配置文件别无他选了。因此,我强烈建议您在集成测试中使用Springockito-annotations,这样你可以最大限度减少测试用例对生产代码的影响,也能消除维护额外XML配置文件的负担。
为Spring工程写集成测试真是简单多了吧,文章中的代码参考自。
译文链接:
英文原文:
翻译作者:&– Sandbox Wang
[&转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]
在文章中找不到问题答案?您还可以
热门栏目订阅}

我要回帖

更多关于 cai yun man tian 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信