Java 使用非空模拟对象进行InjectMock?
我正在执行InjectMock,我得到了这个错误:“java.lang.NullPointerException:…被标记为非null,但为null”,这是由于我进行了非null检查。我想做的是形成一个InjectMock,但是这个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
@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),但是忘记了在我的示例中包含它