我有一个我想测试的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
不显示,我无法在那里设置任何断点,因为它被mock了。addPet
中唯一可以为空的引用是pr
,但当我使用curl发送请求时它可以正常工作。
我还尝试添加
@BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}
因为它是在这里建议的,但它给出了一个初始化异常:
com.example.petstore.backend.api.implementation.PetControllerTest > initializationError FAILED
org.junit.platform.commons.JUnitException at LifecycleMethodUtils.java:57
我如何调试这个?
我如何才能让它工作?
您在这里混合了来自各种测试框架的注释。如果您希望使用Mockito注释@InjectMocks
,那么我建议您根本不要使用任何与Spring相关的mocking注释,而是使用@Mock
注释来创建您要注入的bean的模拟版本(到@InjectMocks
-注释字段中)。还要确保您使用@Exenswith(MockitoExtension. class)
引导Mockito扩展。类似于:
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)
,例如,如果您不想使用MockitoExency
,则需要使用@Before各
注释方法。它们本质上是相同的,但在JUnit Jupiter中不太必要,因为您可以扩展具有多个扩展的测试类,这在JUnit 4.x中是不可能的。因此,如果您想使用Spring上下文和Mockito引导测试,那么您必须选择其中一个并自己设置另一个。