如何模拟测试之外的方法class?

How to mock a method which is outside the test class?

我的代码:

class C:

public class C{
    public int methodC(){
        return 1000;
    }
}

class乙:

public class B{
    private static C c;
    public static int methodB(){
        int b = c.methodC();
        return b;
    }
}

class答:

public class A {
    public int methodA(){
        int a = B.methodB();
        return a;
    }
}

class 测试 A:

class TestA{

    @InjectMocks
    A a;
    @Mock
    C c;
    public void testMethodA(){
        when(c.methodC()).thenReturn(5);
        int result = a.methodA();
        assertEquals(result, 5);
    }
}

即使我模拟 c.methodC()methodC 调用 methodB returns null.

如何模拟 methodC 调用?

我无法更改源代码,只能在 TestA class 中进行更改 我也不能使用 PowerMockito

@Nikhil 根据您对所提问题的更新,完善了我的答案。

Mockito 无法进行静态模拟,正如您所说不能使用 PowerMock 那么@Jnorman 的回答很好。使用 spring 启动和 mockito 来实现这一点,您必须修改 spring 启动启动器测试依赖项以添加新版本的 Mockito,因为 Mockito 3.4.0 支持静态模拟。

Mockito GitHub Link

https://github.com/mockito/mockito/issues/1013

修改后的 POM

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.mockito</groupId>
                    <artifactId>mockito-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.mockito</groupId>
                    <artifactId>mockito-junit-jupiter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>3.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>3.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>3.4.0</version>
            <scope>test</scope>
        </dependency>

修改代码

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import java.lang.reflect.Method;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.Invocation;
import org.mockito.invocation.InvocationFactory;
import org.mockito.invocation.MockHandler;

public class TestA {
  @Test
  public void testMethodA() {
    A a = new A();
    mockStatic(B.class);
    when(B.methodB()).thenReturn(5);
    int result = a.methodA();
    assertEquals(result, 5);
  }
}

class A {

  public int methodA() {
    int a = B.methodB();
    return a;
  }
}

class B {
  private static C c;
  public static int methodB() {
    int b = c.methodC();
    return b;
  }
}

class C {
  public int methodC() {
    return 1000;
  }
}

这是一种使用您的约束使其工作的方法:

    A a = new A();
    C c = Mockito.mock(C.class);
    
    @Test
    public void testMethodA(){
        try {
            Field c = B.class.getDeclaredField("c");
            c.setAccessible(true);
            c.set(null, this.c);
        } catch (Exception e) {
            e.printStackTrace();
        } 
        Mockito.when(c.methodC()).thenReturn(5);
        int result = a.methodA();

        assertEquals(result, 5);       
    }

Mockito [3.4.0] can mock static methods!

依赖性

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>3.4.0</version>
            <scope>test</scope>
        </dependency>

A测试

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mockStatic;

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

public class ATest {

    A a = new A();
    MockedStatic<B> b = mockStatic( B.class );

    @Test
    public void testMethodA() {
        b.when( B::methodB ).thenReturn( 5 );
        assertEquals( a.methodA(), 5 );
    }
}