Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lambada调用mock不生效 #36

Closed
8DE4732A opened this issue Jan 6, 2021 · 9 comments
Closed

lambada调用mock不生效 #36

8DE4732A opened this issue Jan 6, 2021 · 9 comments
Labels
enhancement New feature or request

Comments

@8DE4732A
Copy link

8DE4732A commented Jan 6, 2021

被测类:

    public String process(String source) {
        List<Function<String, String>> processChain = new ArrayList<>();
        processChain.add(this::function1);
        processChain.add(this::function2);
        String temp = source;
        for(Function<String, String> f : processChain) {
            temp = f.apply(temp);
        }
        return temp;
    }

    private String function1(String source) {
        return "*" + source;
    }

    private String function2(String source) {
        return "#" + source;
    }

    public String process2(String source) {
        return function2(function1(source));
    }

test:

    private DemoLambada demoLambada = new DemoLambada();

    @MockMethod(targetClass = DemoLambada.class)
    private String function1(String source) {
        return "mock1" + source;
    }

    @MockMethod(targetClass = DemoLambada.class)
    private String function2(String source) {
        return "mock2" + source;
    }

    // 不通过
    @Test
    public void test_process() {
        Assertions.assertEquals("mock2mock1s", demoLambada.process("s"));
    }

    @Test
    public void test_process2() {
        System.out.println(demoLambada.process2("s"));
        Assertions.assertEquals("mock2mock1s", demoLambada.process2("s"));
    }
@8DE4732A
Copy link
Author

8DE4732A commented Jan 6, 2021

只能mock Function了?

@linfan
Copy link
Collaborator

linfan commented Jan 7, 2021

目前确实还不支持。

原理上TestableMock是在测试运行时对“方法调用”进行扫描和Mock替换,通过 方法引用 或者 函数式接口 进行调用时候,调用语句实际是比如apply()之类,和Mock方法的定义没匹配上。

类似的情况还有,下面这个语句里的handleString()可以Mock:

list.stream().map(it -> handleString(it))

但换成下面这种引用的方式就会Mock失败:

list.stream().map(this::handleString)

理论上能适配,这个问题我先标记一个改进项。
接下来的0.5版本会对底层的实现机制做一次幅度稍大的重构,为了避免给新旧版本兼容留下太多工作量,与底层机制相关的改进项都统一排到0.5版本之后再开始。到主线版本的功能开发完成之后会继续跟进。

@linfan linfan added the enhancement New feature or request label Jan 7, 2021
@VicDelacroix
Copy link

@linfan 追问一下这个问题的进度,谢谢

@linfan
Copy link
Collaborator

linfan commented Apr 7, 2021

目前还没开始处理,尽量在0.6.x版本里支持哈(0.7.0之前)

@VicDelacroix
Copy link

@linfan 更新到了0.6.5,被测类实例创建时
如果直接new则Mock失败(现存问题)
改用OmniConstructor创建则Mock成功,请问这是为什么?

@linfan
Copy link
Collaborator

linfan commented May 21, 2021

@VicDelacroix 如果OmniConstructor创建的对象可用,可能与一处已知BUG有关,已录为issue-163,计划在0.7版本修复

@JiaRG JiaRG mentioned this issue Sep 22, 2021
@zcbbpo
Copy link
Contributor

zcbbpo commented Sep 22, 2021

instruction.getOpcode() == Opcodes.INVOKEDYNAMIC
这种情况下需要特殊处理下,jvm 不会帮我们生成像这种方法
private /* synthetic */ String lambda$methodReference$0
我们可以自己处理下,使用asm生成这个方法,再修改org.objectweb.asm.Handle的name为刚才创建的方法名, 这样就可以mock方法引用的了。

@JiaRG
Copy link

JiaRG commented Oct 12, 2021

@zcbbpo 单个单元测试是可以通过,但是执行整体的测试 lambda 的单测则不通过

@linfan
Copy link
Collaborator

linfan commented Oct 17, 2021

已发布0.6.9版本,包含此PR,感谢@zcbbpo

@JiaRG 是指项目中Demo项目还是指其他单测呢,我这里验证了整体执行Demo单测也是通过的,如果有其他可复现的问题,可另提Issue

@linfan linfan closed this as completed Oct 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants