NullPointerException在injectedMock中。

huangapple go评论73阅读模式
英文:

NullPointerException in injectedMock

问题

以下是您要翻译的内容:

我有一个Rest控制器需要进行测试

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

此处提供的翻译内容应该满足您的要求。如果您有任何其他问题或需要进一步的帮助,请随时提问。

英文:

I have a RestController that I want to test:

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&lt;Pet&gt; addPet(@Valid Pet pet) {
pr.save(new PetBE(9L, &quot;dummy&quot;));
return new ResponseEntity&lt;Pet&gt;(pet, HttpStatus.OK);
}
}
import org.springframework.data.repository.CrudRepository;
public interface PetRepository extends CrudRepository&lt;PetBE, Long&gt; {
}

I want to mock PetRepository and test if the object passed is the object returned:

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(&quot;Klaus&quot;);
assertNotNull(petController);
/*L35*/	ResponseEntity&lt;Pet&gt; r = petController.addPet(p1);
assertEquals(new ResponseEntity&lt;Pet&gt;(p1, HttpStatus.OK), r);
}
}

When I run this method as a gradle test, I get

com.example.petstore.backend.api.implementation.PetControllerTest &gt; testAddPet() FAILED
java.lang.NullPointerException at PetControllerTest.java:35

which is petController.addPet(p1);.

My printlns in addPet are not displayed and I can't set any breakpoints there because it is mocked. The only reference in addPet that could be null is pr, but it works fine when I send a request with curl.
I've also tried adding

	@BeforeAll
public void setup() {
MockitoAnnotations.initMocks(this);
}

because it was suggested here but that gave an InitializationException:

com.example.petstore.backend.api.implementation.PetControllerTest &gt; initializationError FAILED
org.junit.platform.commons.JUnitException at LifecycleMethodUtils.java:57

How can I debug this?
How can I get this to work?

答案1

得分: 2

你混合了来自各种测试框架的注解。如果你想使用Mockito注解@InjectMocks,我建议不使用任何与Spring相关的模拟注解,而是使用@Mock注解来创建要注入的bean的模拟版本(注入到@InjectMocks注解的字段中)。还要确保使用@ExtendWith(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);
    }
}

编辑: 如果你不想使用MockitoExtension,则在例如@BeforeEach注解的方法内部调用MockitoAnnotations.initMocks(this)是必要的。它们本质上是相同的,但在JUnit Jupiter中它不是那么必要,因为你可以将一个测试类扩展为多个扩展,而在JUnit 4.x中是不可能的。所以,如果你想要同时引导你的测试使用Spring上下文和Mockito,那么你必须选择其中一个并自己设置另一个。

英文:

You're mixing annotations from various testing frameworks here. If you wish to use the Mockito annotation @InjectMocks then I'd recommend not using any Spring-related mocking annotations at all, but rather the @Mock annotation to create a mocked version of the bean you want to inject (into the @InjectMocks-annotated field). Also make sure you bootstrap the Mockito extension with @ExtendWith(MockitoExtension.class). Something like:

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(&quot;Klaus&quot;);
        assertNotNull(petController);
        ResponseEntity&lt;Pet&gt; r = petController.addPet(p1);
        assertEquals(new ResponseEntity&lt;Pet&gt;(p1, HttpStatus.OK), r);
    }
}

EDIT: Calling MockitoAnnotations.initMocks(this) inside for example a @BeforeEach-annotated method is necessary if you don't want to use the MockitoExtension. They're essentially the same thing, but it's less necessary in JUnit Jupiter because you can extend a test class with multiple extensions, which was not possible in JUnit 4.x. So if you wanted to bootstrap your test with both a Spring context and Mockito, then you had to pick one of them and setup the other one yourself.

huangapple
  • 本文由 发表于 2020年10月11日 20:09:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/64303841.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定