如何存根 class 中从另一个 class 调用的方法

how to stub a method in a class which is called from another class

public class A {
    .
    .
    .
    public static String methodA() {
        String x = new B().methodX();
        return x + "how are ya?";
    }
}
public class B {
    .
    .
    public String methodX() {
        return "Hello!";
    }
}

@Test
public void testGreeting() {
    final B b = Mockito.spy(new B());
    Mockito.when(b.methodX()).thenReturn("Hi!");

    String greetings = A.methodA();
    // greetings -> "Hello" but i want it to be "Hi!".
}

我无法使我的方法达到 return 所需的值。 上面的实现显示了我是如何编写测试的,但是它没有用。

我做错了什么?

要完成 wakio 编写的答案,您可以编写:

而不是您的代码
public class A {
    private B b;

    public String methodA() {
        String x = b.methodX();
        return x + "how are ya?";
    }

    public void setB(B b) {
        this.b = b;
    }
}

public class B {
    public String methodX() {
        return "Hello!";
    }
}

@Test
public void testGreeting() {
    B b = Mockito.mock(B.class);
    Mockito.when(b.methodX()).thenReturn("Hi!");

    A a = new A();
    a.setB(b);

    String greetings = a.methodA();
    // The result will be "Hi!"
}

但要澄清给定的答案:你的错误是你实际上没有在任何地方使用 spy/mock。

在你的 class A 中你有一个静态方法,其中总是实例化一个新的 B 而不是使用你的间谍:

String x = new B().methodX();

Spy 不会以某种方式使 class 全局 spied 而是仅创建一个被监视并可以被模拟的实例。再说一遍:这个 new B() 既不是间谍也不是嘲讽。

一个可能可行的解决方案是稍微改变你的设计(正如已经建议的那样)并让 Mockito 在 A 的实例中注入这个间谍 B:

@RunWith(MockitoJUnitRunner.class)
public class TestClass {

    public static class AlternativeA {
        // this B can be injected and replaced with a spy or mock
        private B b = new B();
        // get rid of static to use spied B
        public String methodA() {
            String x = b.methodX();
            return x + "how are ya?";
        }
    }

    // Using annotations to create and inject mocks
    @Spy
    private B b;
    @InjectMocks
    private AlternativeA a;
    
    @Test
    public void testGreeting() {
        Mockito.when(b.methodX()).thenReturn("Hi!");
        String greetings = a.methodA();
    }
}