injectedMock 中的 NullPointerException
NullPointerException in injectedMock
我有一个要测试的 RestController:
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PetController implements PetApi {
@Autowired
PetRepository pr;
@Override
public ResponseEntity<Pet> addPet(@Valid Pet pet) {
pr.save(new PetBE(9L, "dummy"));
return new ResponseEntity<Pet>(pet, HttpStatus.OK);
}
}
import org.springframework.data.repository.CrudRepository;
public interface PetRepository extends CrudRepository<PetBE, Long> {
}
我想模拟 PetRepository
并测试传递的对象是否是返回的对象:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.example.petstore.backend.api.model.Pet;
import com.example.petstore.backend.db.PetRepository;
import com.example.petstore.backend.db.PetBE;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
@SpringBootTest
public class PetControllerTest {
@InjectMocks
private PetController petController;
@MockBean
private PetRepository pr;
@Test
void testAddPet() {
when(pr.save(any(PetBE.class))).then(returnsFirstArg());
Pet p1 = new Pet().id(5L).name("Klaus");
assertNotNull(petController);
/*L35*/ ResponseEntity<Pet> r = petController.addPet(p1);
assertEquals(new ResponseEntity<Pet>(p1, HttpStatus.OK), r);
}
}
当我运行这个方法作为gradle测试时,我得到
com.example.petstore.backend.api.implementation.PetControllerTest > testAddPet() FAILED
java.lang.NullPointerException at PetControllerTest.java:35
也就是 petController.addPet(p1);
.
我在 addPet
中的 println
没有显示,我不能在那里设置任何断点,因为它被模拟了。 addPet
中唯一可能为 null 的引用是 pr
,但当我使用 curl 发送请求时它工作正常。
我也试过添加
@BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}
因为有人建议 here 但这给出了 InitializationException:
com.example.petstore.backend.api.implementation.PetControllerTest > initializationError FAILED
org.junit.platform.commons.JUnitException at LifecycleMethodUtils.java:57
我该如何调试它?
我怎样才能让它工作?
您在这里混合了来自各种测试框架的注释。如果您希望使用 Mockito 注释 @InjectMocks
那么我建议您根本不要使用任何 Spring-related 模拟注释,而是使用 @Mock
注释来创建您想要的 bean 的模拟版本注入(进入 @InjectMocks
-注释字段)。还要确保 bootstrap Mockito 扩展 @ExtendWith(MockitoExtension.class)
。类似于:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.example.petstore.backend.api.model.Pet;
import com.example.petstore.backend.db.PetRepository;
import com.example.petstore.backend.db.PetBE;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
@ExtendWith(MockitoExtension.class)
public class PetControllerTest {
@InjectMocks
private PetController petController;
@Mock
private PetRepository pr;
@Test
void testAddPet() {
when(pr.save(any(PetBE.class))).then(returnsFirstArg());
Pet p1 = new Pet().id(5L).name("Klaus");
assertNotNull(petController);
ResponseEntity<Pet> r = petController.addPet(p1);
assertEquals(new ResponseEntity<Pet>(p1, HttpStatus.OK), r);
}
}
编辑: 在内部调用 MockitoAnnotations.initMocks(this)
例如,如果您不想使用 [=17=,则需要 @BeforeEach
-注释方法].它们本质上是相同的东西,但在 JUnit Jupiter 中没那么必要,因为您可以使用多个扩展来扩展测试 class,这在 JUnit 4.x 中是不可能的。因此,如果您想 bootstrap 使用 Spring 上下文 和 Mockito 进行测试,那么您必须选择其中一个并自己设置另一个。
我有一个要测试的 RestController:
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PetController implements PetApi {
@Autowired
PetRepository pr;
@Override
public ResponseEntity<Pet> addPet(@Valid Pet pet) {
pr.save(new PetBE(9L, "dummy"));
return new ResponseEntity<Pet>(pet, HttpStatus.OK);
}
}
import org.springframework.data.repository.CrudRepository;
public interface PetRepository extends CrudRepository<PetBE, Long> {
}
我想模拟 PetRepository
并测试传递的对象是否是返回的对象:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.example.petstore.backend.api.model.Pet;
import com.example.petstore.backend.db.PetRepository;
import com.example.petstore.backend.db.PetBE;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
@SpringBootTest
public class PetControllerTest {
@InjectMocks
private PetController petController;
@MockBean
private PetRepository pr;
@Test
void testAddPet() {
when(pr.save(any(PetBE.class))).then(returnsFirstArg());
Pet p1 = new Pet().id(5L).name("Klaus");
assertNotNull(petController);
/*L35*/ ResponseEntity<Pet> r = petController.addPet(p1);
assertEquals(new ResponseEntity<Pet>(p1, HttpStatus.OK), r);
}
}
当我运行这个方法作为gradle测试时,我得到
com.example.petstore.backend.api.implementation.PetControllerTest > testAddPet() FAILED
java.lang.NullPointerException at PetControllerTest.java:35
也就是 petController.addPet(p1);
.
我在 addPet
中的 println
没有显示,我不能在那里设置任何断点,因为它被模拟了。 addPet
中唯一可能为 null 的引用是 pr
,但当我使用 curl 发送请求时它工作正常。
我也试过添加
@BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}
因为有人建议 here 但这给出了 InitializationException:
com.example.petstore.backend.api.implementation.PetControllerTest > initializationError FAILED
org.junit.platform.commons.JUnitException at LifecycleMethodUtils.java:57
我该如何调试它?
我怎样才能让它工作?
您在这里混合了来自各种测试框架的注释。如果您希望使用 Mockito 注释 @InjectMocks
那么我建议您根本不要使用任何 Spring-related 模拟注释,而是使用 @Mock
注释来创建您想要的 bean 的模拟版本注入(进入 @InjectMocks
-注释字段)。还要确保 bootstrap Mockito 扩展 @ExtendWith(MockitoExtension.class)
。类似于:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.example.petstore.backend.api.model.Pet;
import com.example.petstore.backend.db.PetRepository;
import com.example.petstore.backend.db.PetBE;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
@ExtendWith(MockitoExtension.class)
public class PetControllerTest {
@InjectMocks
private PetController petController;
@Mock
private PetRepository pr;
@Test
void testAddPet() {
when(pr.save(any(PetBE.class))).then(returnsFirstArg());
Pet p1 = new Pet().id(5L).name("Klaus");
assertNotNull(petController);
ResponseEntity<Pet> r = petController.addPet(p1);
assertEquals(new ResponseEntity<Pet>(p1, HttpStatus.OK), r);
}
}
编辑: 在内部调用 MockitoAnnotations.initMocks(this)
例如,如果您不想使用 [=17=,则需要 @BeforeEach
-注释方法].它们本质上是相同的东西,但在 JUnit Jupiter 中没那么必要,因为您可以使用多个扩展来扩展测试 class,这在 JUnit 4.x 中是不可能的。因此,如果您想 bootstrap 使用 Spring 上下文 和 Mockito 进行测试,那么您必须选择其中一个并自己设置另一个。