Spring AOP Aspect 无法使用 Mockito 工作

2024-01-25

我有一个@Aspect它编织了我所有控制器操作方法的执行。当我运行系统时它工作得很好,但在单元测试中却不行。我按以下方式使用 Mockito 和 junit:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:**/spring-context.xml")
@WebAppConfiguration
public class UserControllerTest {        
    private MockMvc mockMvc;

    @Mock
    private RoleService roleService;

    @InjectMocks
    private UserController userController;

    @Before
    public void setUp() {
       MockitoAnnotations.initMocks(this);                    
       ...    
       mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
    }    
    ...
}

和一些@Test using mockMvc.perform().

而我的看点是:

@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controller() { }

@Pointcut("execution(* mypackage.controller.*Controller.*(..))")
public void methodPointcut() { }

@Around("controller() && methodPointcut()")
...

首先,需要按照 Jason 的建议使用 webAppContextSetup:

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() throws Exception {
   ...
   mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

此时应该触发切面,但 Mockito 不会注入模拟。这是因为 Spring AOP 使用代理对象,并且模拟被注入到该代理对象而不是被代理对象。要解决此问题,需要解开对象并使用 ReflectionUtils 而不是 @InjectMocks 注释:

private MockMvc mockMvc;

@Mock
private RoleService roleService;

private UserController userController;

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() {
   MockitoAnnotations.initMocks(this);                    
   UserController unwrappedController = (UserController) unwrapProxy(userController);
   ReflectionTestUtils.setField(unwrappedController, "roleService", roleService);   
   mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

...

public static final Object unwrapProxy(Object bean) throws Exception {
/*
 * If the given object is a proxy, set the return value as the object
 * being proxied, otherwise return the given object.
 */
    if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
        Advised advised = (Advised) bean;
        bean = advised.getTargetSource().getTarget();
    }
    return bean;
}

此时,任何对when(...).thenReturn(...) 的调用都应该正常工作。

这里解释一下:http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring AOP Aspect 无法使用 Mockito 工作 的相关文章

随机推荐

  • MYSQL触发器更新复制整行

    我正在尝试创建一个触发器来将整行复制到任何UPDATE 我有2张桌子 Frequencies and Frequencies Audit 这是我的触发器 create trigger auditlog before update on fr
  • 通过 VueJS 2 重用模态

    我在 JSFiddle 使用 Vue 版本 1 中看到了重用模式 https jsfiddle net kemar d3jecL8n https jsfiddle net kemar d3jecL8n 但是当我换成Vue 2版本时 就不行了
  • GNUPLOT:从平滑累积中保存数据

    我绘制了实数均匀随机分布 n 1000 的简单累积和直方图 http www filedropper com random1 1 http www filedropper com random1 1 随机1天 宏是 unset key cl
  • React 组件是否会深入比较 props 以检查是否需要重新渲染?

    我想知道 React 组件是否扩展React Component在尝试决定是否需要重新渲染时对对象进行深入比较 例如 给定 const Foo bar gt return div bar baz div class App extends
  • Titanium Desktop 中的 SVG?

    我正在运行 Titanium Desktop 1 1 0 SDK 并且只有我的 SVG 文本元素可以正确呈现 SVG 方法 例如 getBBox 会给出错误消息 该应用程序在 Titanium 环境之外运行良好 即 Chrome Firef
  • 支持可选参数和.Net 4.0的C#模拟框架

    是否存在完全支持 Net 4 0 和 C 的 C 模拟框架 具体来说 我正在寻找它支持可选参数 我能够通过编写一个扩展方法来让 Moq 来处理这个问题 该方法接受方法名称以及参数名称和值的字典 did想要指定 并且扩展方法为您未指定的所有参
  • Docker Compose + Rails:迁移的最佳实践?

    我刚刚关注了这篇文章在 Docker 中运行 Rails 开发环境 https blog codeship com running rails development environment docker 好文章 效果很好 设置完所有内容后
  • 离子启动给出错误:生成的命令有错误:npminstall

    我正在尝试使用 ionic 和 cordova 创建一个移动应用程序 但是当我启动命令时 ionic start appname blank 下载后 npm 给我 Error with start undefined Error Initi
  • ActionBarSherlock 4.2 是否支持 SearchView 的搜索建议?

    一个月前 我将 ActionBarSherlock 4 2 添加到我的项目中 除了我的搜索建议之外 一切都正常工作了SearchView 我创建搜索建议的方式是使用Android文档中的方法 http developer android c
  • Windows Phone 7.1“发送到”功能?

    我被要求用 C 为 Windows Phone 7 1 编写一个原型应用程序 该应用程序可以通过 Android 的 共享 功能等功能获取数据 然后处理这些数据 例如 用户打开邮件应用程序并查看 PDF 附件 对于此附件 他按下应用程序的
  • 出现错误:部署到 heroku 时必须至少安装一个 postgresql-client-

    sdilshod sdilshod Lenovo B590 webapp saturn heroku run rake db migrate Running rake db migrate attached to terminal up r
  • mpi4py 中的共享内存

    I use a MPI mpi4py 脚本 在单个节点上 适用于非常大的对象 为了让所有进程都能访问该对象 我通过comm bcast 这会将对象复制到所有进程并消耗大量内存 尤其是在复制过程中 因此 我想分享一些像指针这样的东西 而不是对
  • 迭代 hastable 键的枚举会引发 NoSuchElementException 错误

    我正在尝试使用枚举来迭代哈希表中的键列表 但是我在列表中的最后一个键处不断收到 NoSuchElementException Hashtable
  • ListBox 中的 DataTextField 是 2 个字段的组合

    我有一个包含用户的列表框 数据源是 User 类型的通用列表 包含 id firstname lastname 现在我想使用 id 作为数据值 通过 dataValueField 并且我想要 LastName Firstname 作为 Da
  • 为什么在图像和 CSS 文件之后查询字符串?

    我在各个网站上看到过一个查询字符串 后面跟着一个图像和 CSS 文件的数字 当我查看源代码 通过 Chrome Developer 时 缓存的 css 文件和图像的名称中没有查询字符串中的数字 我还在网站上看到 当我刷新页面时 查询字符串中
  • 从可迭代的乘积中创建 Pandas MultiIndex?

    当我有两个或多个可迭代对象时 我有一个实用程序函数用于创建 Pandas MultiIndex 并且我想要为这些可迭代对象中的值的每个唯一配对提供一个索引键 看起来像这样 import pandas as pd import itertoo
  • 在javascript中将字符串数组转换为名称/值对象

    我目前正在处理一个向客户端返回字符串数组的 Web 服务 从这里我想获取这个字符串数组并将其转换为一个对象 该对象为每个字符串提供一个名称 以便稍后引用它 所以从这个开始 var result test hello goodbye 我想以此
  • .Net Windows 应用程序 WebBrowser / Google 地图 API v3

    我正在开发一个应用程序 用户可以在其中输入所需的地址 然后按按钮 该地址可以在WebBrowser net windows 应用程序中的控制 我知道你可以运行 javascriptWebBrowser通过使用WebBrowser1 Docu
  • 获取git命令列表

    我想为每个 git 命令创建一个别名 由于它们有很多 我想将它们放在一个列表中 然后在我的循环中循环 bashrc 有什么办法可以将它们写入 shell 脚本中吗 你可以试试这个 git help a 或者 您的 git 命令列在
  • Spring AOP Aspect 无法使用 Mockito 工作

    我有一个 Aspect它编织了我所有控制器操作方法的执行 当我运行系统时它工作得很好 但在单元测试中却不行 我按以下方式使用 Mockito 和 junit RunWith SpringJUnit4ClassRunner class Con