测试代码

package org.simonme.srcstudy.spring3.demo.stub;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.simonme.srcstudy.spring3.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /**
* <一句话功能简述>
* <功能详细描述>
*
* @author http://www.cnblogs.com/simoncook
* @version [版本号, 2017年11月4日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
public class UserServiceAssemblyByJUnit
{ private UserService userService; @Test
public void test()
{
assertNotNull(userService);
} public UserService getUserService()
{
return userService;
} @Autowired
public void setUserService(UserService userService)
{
this.userService = userService;
}

分析方式

this.userService = userService; 这一行直接断点

堆栈信息

org.simonme.srcstudy.spring3.demo.stub.UserServiceAssemblyByJUnit.setUserService(org.simonme.srcstudy.spring3.demo.service.UserService) line: 50
sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) line: not available [native method]
sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 39
sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 25
java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object...) line: 597
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) line: 582
org.springframework.beans.factory.annotation.InjectionMetadata.inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) line: 84
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(org.springframework.beans.PropertyValues, java.beans.PropertyDescriptor[], java.lang.Object, java.lang.String) line: 282
org.springframework.beans.factory.support.DefaultListableBeanFactory(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory).populateBean(java.lang.String, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.BeanWrapper) line: 1074
org.springframework.beans.factory.support.DefaultListableBeanFactory(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory).autowireBeanProperties(java.lang.Object, int, boolean) line: 374
org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(org.springframework.test.context.TestContext) line: 110
org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(org.springframework.test.context.TestContext) line: 75
org.springframework.test.context.TestContextManager.prepareTestInstance(java.lang.Object) line: 321
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest() line: 220
org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall() line: 301
org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1(org.junit.internal.runners.model.ReflectiveCallable).run() line: 12
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(org.junit.runners.model.FrameworkMethod) line: 303
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier) line: 240
org.springframework.test.context.junit4.SpringJUnit4ClassRunner(org.junit.runners.BlockJUnit4ClassRunner).runChild(java.lang.Object, org.junit.runner.notification.RunNotifier) line: 50
org.junit.runners.ParentRunner$3.run() line: 238
org.junit.runners.ParentRunner$1.schedule(java.lang.Runnable) line: 63
org.springframework.test.context.junit4.SpringJUnit4ClassRunner(org.junit.runners.ParentRunner<T>).runChildren(org.junit.runner.notification.RunNotifier) line: 236
org.junit.runners.ParentRunner<T>.access$000(org.junit.runners.ParentRunner, org.junit.runner.notification.RunNotifier) line: 53
org.junit.runners.ParentRunner$2.evaluate() line: 229

看junit的运作方式

从main方法到runner

翻看官方guide 很容易发现JUnitCore是main方法所在类

JUnitCore是如何到runner的呢? 看下面分析

org.junit.runner.JUnitCore.main(String...)
// 一些listener构造之类,然后通过AllDefaultPossibilitiesBuilder 构建runner
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(Class<?>)
List<RunnerBuilder> builders = Arrays.asList(
ignoredBuilder(),
annotatedBuilder(),
suiteMethodBuilder(),
junit3Builder(),
junit4Builder()); for (RunnerBuilder each : builders) {
Runner runner = each.safeRunnerForClass(testClass);
if (runner != null) {
return runner;
}
}

找到一个就直接返回

ignoredBuilder 可以用过Ignore注解忽略你的test case

annotatedBuilder 是找 RunWith注解定义的自定义runner

junit3Builder 如果test case 继承自TestCase类 则用junit3的runner

junit4Builder 直接对接 BlockJUnit4ClassRunner

spring的SpringJUnit4ClassRunner也是继承自BlockJUnit4ClassRunner

回头去看上面的堆栈信息 一目了然

关键点在于重写 org.junit.runners.BlockJUnit4ClassRunner.createTest() 这个方法

protected Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance();
}
/**
* Delegates to the parent implementation for creating the test instance and
* then allows the {@link #getTestContextManager() TestContextManager} to
* prepare the test instance before returning it.
*
* @see TestContextManager#prepareTestInstance(Object)
*/
@Override
protected Object createTest() throws Exception {
Object testInstance = super.createTest();
getTestContextManager().prepareTestInstance(testInstance);
return testInstance;
}

也就是把JUnit原生的创建test case的instance的过程接用spring容器装配的方式接管过来就可以了。

理一理Spring如何对接JUnit的更多相关文章

  1. spring框架和junit框架结合使用案例

    package ltssh; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.be ...

  2. Spring Boot 解决方案 - JUnit 测试

    简单的 JUnit 项目 回顾一下创建并运行简单的 JUnit 测试项目,先添加 JUnit 依赖然后编写类似如下模板的测试类,使用 IDE 的话直接用插件运行就行, 使用 Maven 的话运行命令 ...

  3. Spring框架下Junit测试

    Spring框架下Junit测试 一.设置 1.1 目录 设置源码目录和测试目录,这样在设置产生测试方法时,会统一放到一个目录,如果没有设置测试目录,则不会产生测试代码. 1.2 增加配置文件 Res ...

  4. Spring中的Junit

    Spring中的Junit package com.imooc.test.base; import org.junit.After; import org.junit.Before; import o ...

  5. spring入门-整合junit和web

    整合Junit 导入jar包 基本 :4+1 测试:spring-test-5.1.3.RELEASE.jar 让Junit通知spring加载配置文件 让spring容器自动进行注入 1234567 ...

  6. Spring Boot 整合Junit和redis

    14. Spring Boot整合-Junit 目标:在Spring Boot项目中使用Junit进行单元测试UserService的方法 分析: 添加启动器依赖spring-boot-starter ...

  7. [Java] Spring + SpringMVC + Maven + JUnit 搭建

    示例项目下载: https://github.com/yangyxd/SpringDemo 利用前面 SpringMVC 项目的配置方式,完成初步的项目创建.下面只讲一些不同之处. 传送门: [Jav ...

  8. spring && Cobertura && maven &&junit 单元测试以及测试覆盖率

    1. 目的:       junit 单元测试,Cobertura   测试覆盖率报告       项目目录结构          2. maven 配置     <project xmlns= ...

  9. Spring MVC实现Junit Case

    Spring MVC中编写单元测试(WEB项目): 1. 首先开发一个基类,用于载入配置文件.以下所有的测试实现类都要继承这个类 package com.yusj.basecase; import o ...

随机推荐

  1. 从零开始的Lua宅[1]:编译Lua解释器

    Lua是一门神奇的脚本语言,游戏宅必备,懒人必备.Lua差多不是学起来用起来最简单的语言了,以至于简单到自身就是文档,自身就是配置文件.但是Lua的运行效率却是众多脚本中非常高的,据说仅次于V8爹下的 ...

  2. ios 根据字典自动生成属性

    - (void)createPropertyCode{ NSMutableString *codes = [NSMutableString string]; // 遍历字典 [self enumera ...

  3. 【虚拟机-虚拟网络】使用 PsPing & PaPing 进行 TCP 端口连通性测试

    PsPing & PaPing 介绍 通常,我们测试数据包能否通过 IP 协议到达特定主机时,都习惯使用 ping 命令.工作时 ping 向目标主机发送一个 IMCP Echo 请求的数据包 ...

  4. 编写生成32位大写和小写字符的md5的函数

    package nicetime.com.practise; import java.security.MessageDigest; /** * MD5加密是JAVA应用中常见的算法,请写出两个MD5 ...

  5. iOS 学习随记 (一)

    入行IT也已经很多年了,厌倦了Windows平台的工作, 4月初突然抽风买了台Mac就开始决定转身做iOS/OS X下的App开发了. 从适应Mac机器到开始编程没有花费太长时间,也因为有C#和Jav ...

  6. img标签src资源无法加载,报net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION错

    html代码: chrome和360浏览器均报错,系统自带IE.Firefox浏览器没有问题 原因:加载的资源名含有半角逗号(,)或者别的特殊符号 解决办法:后台给资源名加上双引号("&qu ...

  7. IIS 7.0的根文件(applicationHost.config)位置及说明

    位置 C:\Windows\System32\inetsrv\config\applicationHost.config 说明 https://www.microsoft.com/taiwan/tec ...

  8. Android(java)学习笔记125:保存数据到SD卡 (附加:保存数据到内存)

    1. 如果我们要想读写数据到SD卡中,首先必须知道SD的路径: File file = new File(Environment.getExternalStorageDirectory()," ...

  9. python之golbal/nonlocal

    一.关键字 golbal nonlocal 在局部修改全局的变量为什么会报错 count = 0 def func(): count += 1 func() # UnboundLocalError: ...

  10. [BZOJ4327]:[JZOI2012]玄武密码(AC自动机)

    题目传送门 题目描述: 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此.  ...