jjzjj

java - Mockito:是否可以将 mock 与方法名称结合起来在 when() 调用中创建 methodCall?

coder 2024-03-19 原文

我在 StackOverflow 上的第一个问题。我希望能够做类似的事情:

SomeClass mock = mock(SomeClass.class);

String methodName = "someMethod";或方法方法 = ...someMethod...

这两个东西(mock 和方法)将结合起来执行以下操作:

when(mock.someMethod()).thenReturn(null);

当然,'null' 值会根据我的需要进行相应更改,但我试图确定两件事:

1) 是否有可能在 Java 中执行类似this 的操作? This = 将类对象和方法组合到 methodCall 中。

2) 我该怎么做?

我一直在研究这个,但我找不到任何东西。问题是,即使这适用于常规类和常规方法(someClass 和 someMethod 会一起执行 someClass.someMethod()),请记住,这必须适用于模拟对象 用于 when() 调用。

回答:when(method.invoke(mock)).thenReturn("Hello world.");是正确的语法并且反射确实在 when() 调用中起作用。谢谢凯文韦尔克!

最佳答案

既然你基本上是让我重新发布我的评论,根据你的回复修改,作为答案,这里是:

尝试像这样使用反射:

when(method.invoke(mock)).thenReturn("Hello world.");

尽管如此,我不确定这对您有何作用,因为您不能模拟/监视类 Method(它是最终的)。 Mockito 的 when() 仅适用于模拟或 spy 。如果这真的对你有用,你能发布更多细节吗?

如果它不起作用,您可以——正如我在 OP 的评论中所建议的那样——走 CGLib 路线并绕过 Mockito。这真的没有乍看起来那么难。在我的 OSS 项目中 Funcito (不是 模拟框架),我剥离了很多 Mockito CGLib 代理代码并根据我的需要重写了它。它为代理类和拦截方法调用的世界提供了一个更简单的 View 。

对评论的补充回复 我知道这是如何为你工作的,但我不确定你是否真的理解它是如何工作的。这可能很重要,因为 Mockito 本身工作方式的 future 变化可能会导致您的解决方案在未来崩溃。从本质上讲,它起作用的原因几乎是偶然的,但它确实会起作用。

when() 应该工作的方式是括号之间发生的是对先前创建的 Mockito 生成的模拟或 spy 的方法调用,这只是类,而不是类的真实实例。代理具有特殊的逻辑,可以拦截伪造的代理方法调用,并将其添加到已注册的代理方法调用列表中(它存储在称为 IOngoingStubbing 或类似的东西中)供以后使用。由于 Java 在调用方法之前评估参数,这保证了代理方法调用在实际执行 when() 方法之前得到注册/记住。 when() 所做的是弹出此 IOngoingStubbing,然后它成为调用 thenReturns() 的对象。

您没有“正确”使用它,但它仍然适用于您。如何?好吧,所有需要发生的事情是需要调用代理上的方法,以便在执行 when() 之前在 IOngoingStubbing 中注册。您不是直接调用代理上的方法,而是通过将代理传递给 Method.invoke() 间接调用代理上的方法。因此满足条件,并且 when() 已经在 IOngoingStubbing 中注册了一个代理方法调用。

你可以在下面的代码中看到同样的“偶然”的快乐,一开始看起来毫无意义,直到你意识到 Mockito 的工作原理:

@Test
public void testSomething() throws Exception {
    List listMock = mock(List.class);
    Method m = List.class.getDeclaredMethod("get", int.class);
    m.invoke(listMock, Mockito.anyInt());

    when(null).thenReturn("Hello World");  // Huh? passing null?

    assertEquals("Hello World", listMock.get(0)); // works!
}

上面的测试居然通过了!即使 when 的参数为 null,重要的是代理(即模拟)实例在调用 when 语句之前调用了正确的方法。

虽然 Mockito 不太可能改变幕后工作的基本方式,但在未来的某个时候它仍然有可能被打破。就像我说的,它起作用或多或少是一个幸运的意外。只要您了解它的工作方式和所涉及的风险,您就会拥有更多的力量。

关于java - Mockito:是否可以将 mock 与方法名称结合起来在 when() 调用中创建 methodCall?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10124482/

有关java - Mockito:是否可以将 mock 与方法名称结合起来在 when() 调用中创建 methodCall?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  6. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  9. Ruby 元类 : why three when defined singleton methods? - 2

    让我们计算MRI范围内的类别:defcount_classesObjectSpace.count_objects[:T_CLASS]endk=count_classes用类方法定义类:classAdefself.foonilendend然后运行:putscount_classes-k#=>3请解释一下,为什么是三个? 最佳答案 查看MRI代码,每次你创建一个Class时,在Ruby中它是Class类型的对象,ruby会自动为这个新类创建“元类”类,这是另一个单例类型的Class对象。C函数调用(class.c)是:rb_define

  10. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

随机推荐