Java 使用非空模拟对象进行InjectMock?

Java 使用非空模拟对象进行InjectMock?,java,junit,mockito,Java,Junit,Mockito,我正在执行InjectMock,我得到了这个错误:“java.lang.NullPointerException:…被标记为非null,但为null”,这是由于我进行了非null检查。我想做的是形成一个InjectMock,但是这个InjectMock对象是使用参数构造的 下面是一些伪代码: @ExtendWith(MockitoExtension.class) public class Tester { @Spy private ClassA clA; @InjectMock

我正在执行InjectMock,我得到了这个错误:“java.lang.NullPointerException:…被标记为非null,但为null”,这是由于我进行了非null检查。我想做的是形成一个InjectMock,但是这个InjectMock对象是使用参数构造的

下面是一些伪代码:

@ExtendWith(MockitoExtension.class)

public class Tester {
    @Spy private ClassA clA;
    @InjectMocks 
    private ClassB clB = new clB(clA);


    @BeforeEach
    void setup() throws Exception {
        Mock.when(clA.mymethod(Mockito.any())).thenReturn(Non_Null_Stuff);
    }

}
我相信您可以看到我在这里试图做的事情:使用类a的模拟版本创建类B,但它不起作用,因为它在@InjectMocks行中给出了“clA标记为非null,但为null”。这是因为构造clB的代码需要非空clA

似乎我无法在setup函数中放置injectmock行,也无法在injectmock之前放置Mock.when,因此我被卡住了。非常感谢您的建议,这里有两个问题。 答案取决于你想要实现什么

要使用Mockito注释,您应该在类上方添加下一行(如果您使用jUnit 5):

并且,这种对pom的依赖性(如果您使用Maven(您可以在这里找到Gradle的模拟:))

ClassA:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class Test {

    @Spy
    private ClassA classA; // it will be real object

    @Mock
    private ClassB classB; // it will be mock

    @InjectMocks
    private ClassC classC;

    @org.junit.jupiter.api.Test
    public void test() {

        // for mock we should define it's behaviour for the test (here or in @BeforeEach annotated method)
        Mockito.when(classB.mockedMethod()).thenReturn("Some overridden behaviour");

        String result = classC.someMethod();

        assertEquals("ClassA - Some overridden behaviour", result);

        // verity that method on real object wall called
        Mockito.verify(classA, Mockito.only()).realMethod();

        // verity that method on mocked object wall called
        Mockito.verify(classB, Mockito.only()).mockedMethod();

    }
}
public class ClassA {

    public String realMethod() {
        return "ClassA";
    }
}
public class ClassB {

    public String mockedMethod(){
        return "ClassB";  // we will not be using it's real behaviour
    }
}
public class ClassC {

    private ClassA classA;

    private ClassB classB;

    public ClassC(ClassA classA, ClassB classB) {
        this.classA = classA;
        this.classB = classB;
    }

    public String someMethod() {
        return classA.realMethod() + " - " +classB.mockedMethod();
    }
}
ClassB:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class Test {

    @Spy
    private ClassA classA; // it will be real object

    @Mock
    private ClassB classB; // it will be mock

    @InjectMocks
    private ClassC classC;

    @org.junit.jupiter.api.Test
    public void test() {

        // for mock we should define it's behaviour for the test (here or in @BeforeEach annotated method)
        Mockito.when(classB.mockedMethod()).thenReturn("Some overridden behaviour");

        String result = classC.someMethod();

        assertEquals("ClassA - Some overridden behaviour", result);

        // verity that method on real object wall called
        Mockito.verify(classA, Mockito.only()).realMethod();

        // verity that method on mocked object wall called
        Mockito.verify(classB, Mockito.only()).mockedMethod();

    }
}
public class ClassA {

    public String realMethod() {
        return "ClassA";
    }
}
public class ClassB {

    public String mockedMethod(){
        return "ClassB";  // we will not be using it's real behaviour
    }
}
public class ClassC {

    private ClassA classA;

    private ClassB classB;

    public ClassC(ClassA classA, ClassB classB) {
        this.classA = classA;
        this.classB = classB;
    }

    public String someMethod() {
        return classA.realMethod() + " - " +classB.mockedMethod();
    }
}
ClassC:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class Test {

    @Spy
    private ClassA classA; // it will be real object

    @Mock
    private ClassB classB; // it will be mock

    @InjectMocks
    private ClassC classC;

    @org.junit.jupiter.api.Test
    public void test() {

        // for mock we should define it's behaviour for the test (here or in @BeforeEach annotated method)
        Mockito.when(classB.mockedMethod()).thenReturn("Some overridden behaviour");

        String result = classC.someMethod();

        assertEquals("ClassA - Some overridden behaviour", result);

        // verity that method on real object wall called
        Mockito.verify(classA, Mockito.only()).realMethod();

        // verity that method on mocked object wall called
        Mockito.verify(classB, Mockito.only()).mockedMethod();

    }
}
public class ClassA {

    public String realMethod() {
        return "ClassA";
    }
}
public class ClassB {

    public String mockedMethod(){
        return "ClassB";  // we will not be using it's real behaviour
    }
}
public class ClassC {

    private ClassA classA;

    private ClassB classB;

    public ClassC(ClassA classA, ClassB classB) {
        this.classA = classA;
        this.classB = classB;
    }

    public String someMethod() {
        return classA.realMethod() + " - " +classB.mockedMethod();
    }
}

问题是类C需要用一个不为null的类B中的对象进行实例化。在这种情况下,你会怎么做呢?如果你想使用Spy或Mock(取决于你想要实现什么)中的一个注释,那么类型为B的字段将不会为null。若在类C中有合适的构造函数,若在该字段上方使用InjectMocks注释,Mockito将自动将该对象放入该字段。在这种情况下,您不需要自己创建任何对象,但是结果是空的。知道为什么吗?它在错误消息中说它也是空的,只是为了澄清我确实包含了@ExtendWith(MockitoExtension.class),但是忘记了在我的示例中包含它