【问题标题】:How to mock a method that is called from another method如何模拟从另一个方法调用的方法
【发布时间】:2015-08-11 20:05:37
【问题描述】:

我所处的场景

public class SecondClass{

    SecondClass(FirstClass fc){
    ...
    }

    public void foo(String a,String b){
        ....
    }
}

public class FirstClass{
    private SecondClass sc;
    public void init(){
        sc = new SecondClass(this);
    }

    public void bar(List<Integer> input){
        .....
        sc.foo(s1,s2);
    }
}

我想获取进入 foo 的字符串参数 a 和 b。测试类如下所示

@PrepareForTest({ FirstClass.class, SecondClass.class })
public class SampleTest
{
    private String[] texts;

    @Test
    public void testBar() throws Exception
    {
        texts = new String[2];

        final FirstClass fc = mock(FirstClass.class);
        final SecondClass sc = spy(new SecondClass(fc));

        doAnswer(invocation -> {
            texts = (String[]) invocation.getArguments();
            return null;
        }).when(sc).foo(anyString(), anyString());

        final List<Integer> input = new ArrayList<>();
        input.add(1);
        fc.bar(input);

        System.out.println(texts[0]+"<>"+text[1]);
    }
}

最后的 sysout 打印 nullnull。为什么 texts 数组没有更新?

【问题讨论】:

  • 1/ scSecondClass 中的本地变量,因此您的代码无效(scbar 中未定义) 2/ 在您的测试中,您有一个sc这是一个间谍但是这个sc不是bar中使用的那个(另见1/)
  • 你想测试什么?头等舱的功能?那为什么要嘲笑呢?
  • @RC 我根据您的第 1 点更新了代码。
  • @FlorianSchaetz 我不想测试从 bar 传递的字符串 s1 和 s2。如果我可以在不使用/调用 sc 的情况下在我的测试中实现同样的效果,那么我会走那条路,但不知道该怎么做。
  • 使用真正的FirstClassSecondClass 模拟你以某种方式“注入”(设置器、构造器、反射),这应该可以。

标签: java unit-testing junit powermock powermockito


【解决方案1】:

根本问题是FirstClass 初始化了它自己的SecondClass 副本,而您想提供一个模拟或类似的。

控制反转依赖注入方法旨在通过为类提供操作所需的组件来缓解这种情况。您能否改为将SecondClass 的副本注入FirstClass 中(例如,通过init() 的参数)?这样,您就可以在测试场景中提供模拟,从而测试您的方法调用。

例如

FirstClass fc = new FirstClass();
fc.init(myMockedSecondClass);
fc.bar(...);

// now test the invocations on your mock

【讨论】:

  • 这不是我的选择。我想测试由 bar 方法生成的字符串 s1 和 s2。如果可以在不创建 sc 对象的情况下做到这一点,那么我将选择该路线。我不确定如何不使用 sc,因为 s1 和 s2 是 bar 内的局部变量。
  • 你用 s1 和 s2 在你的 mock 上调用一个方法。因此,您可以断言该方法是使用 特定 值调用的。这确实解决了你的问题
  • 好吧 s1 和 s2 是根据我传递的整数列表生成的。我想测试是否生成了正确的 s1 和 s2 字符串。例如: bar 的输入是一个包含 1 的列表,然后 s1 =“个位数”和 s2 =“正数”。如果 bar 的输入是 -34,则 s1 = "double digit" 和 s2 = "negative"。这有帮助吗?
  • 好吧,如果您在 Mockito 中使用 verify() 方法(例如 - 您使用的任何模拟框架都将提供类似的功能),那么您可以对此进行测试。这是与您在上面所做的类似的调用,除了您将 anyString() 替换为检查所需的字符串(IIRC)
【解决方案2】:

替换这个...

public void init(){
   SecondClass sc = new SecondClass(this);
}

使用 sc 的 Setter,然后在您的测试用例中放一个 Mock,从而使您能够测试 FirstClass 的真实 bar 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多