英文:
NullPointerException when mocking repository JUnit
问题
以下是您提供的翻译好的部分:
我已经创建了一个带有控制器、服务和存储库层的基本 Rest API。我现在正在尝试为查找产品的服务层方法编写单元测试,该方法通过产品ID查找产品。然而,当我运行测试时,在我试图模拟repository的findById()方法的那一行代码中,它抛出了一个空指针异常。
服务层中的getProductById()方法如下:
public Product getProductById(String id){
return productRepository.findById(id).orElse(null);
}
服务层的测试类如下:
package com.product.Services;
import com.product.Entities.Product;
import com.product.Repositories.ProductRepository;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
class ProductServiceTest {
@InjectMocks
ProductService productService;
@Mock
ProductRepository productRepository;
@Test
void getProductById() throws Exception {
Product product = new Product();
product.setId("001");
product.setName("TV");
product.setPrice(999.99);
when(productRepository.findById("001").orElse(null)).thenReturn(product);
assertEquals(product, productService.getProductById("001"));
}
}
附上调试器显示的截图:
英文:
I have created a basic Rest API with a Controller, Service and Repository layer. I am now trying to write a unit test for the Service layer method that finds product by the product id. However, when I run the test it throws a NullPointerException in the line where I am trying to mock the repository findById() method.
The getProductById() method in the service layer is as follows:
public Product getProductById(String id){
return productRepository.findById(id).orElse(null);
}
My test class for the service layer:
package com.product.Services;
import com.product.Entities.Product;
import com.product.Repositories.ProductRepository;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
class ProductServiceTest {
@InjectMocks
ProductService productService;
@Mock
ProductRepository productRepository;
@Test
void getProductById() throws Exception {
Product product = new Product();
product.setId("001");
product.setName("TV");
product.setPrice(999.99);
when(productRepository.findById("001").orElse(null)).thenReturn(product);
assertEquals(product,productService.getProductById("001"));
}
}
答案1
得分: 3
问题在于这里使用了两个不同版本的JUnit:
org.junit.jupiter.api.Test
来自于JUnit5,
而 org.junit.runner.RunWith
来自于JUnit4。
RunWith
在JUnit5中已经不存在了。
在这个特定情况下,我会使用JUnit4 - 即使用注解 org.junit.Test
(而不是 org.junit.jupiter.api.Test
)来注释你的测试。
如何在JUnit5中使用Mockito 提供了其他有效的解决方案。
英文:
The problem is that 2 different versions of JUnit are used here:
org.junit.jupiter.api.Test
is from JUnit5, while
org.junit.runner.RunWith
is from JUnit4.
RunWith
does not exist anymore in JUnit5.
In this specific case, I would use JUnit4 - i.e. use the annotation org.junit.Test
(instead of org.junit.jupiter.api.Test
) to annotate your test.
How to use Mockito with JUnit5 provides other valid solutions.
答案2
得分: 1
JUnit 5 使用 @ExtendWith(SpringExtension.class) 注解,能否将 @RunWith 注解更改并重试?
英文:
JUnit 5 uses @ExtendWith(SpringExtension.class) annotation, can you change @RunWith annotation and try again?
答案3
得分: 0
你应该模拟 findById
调用,而不是与 orElse
链接的表达式:
when(productRepository.findById("001")).thenReturn(product);
英文:
You should mock the findById
call, not the expression chained with orElse
:
when(productRepository.findById("001")).thenReturn(product);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论