我有一个简单的测试用例,我在春季启动应用程序中使用了Mockito。
用户操作.java
...
@Autowired
Validator nameValidator;
private boolean userOperation(String name) {
NameStats nameStats = nameValidator.validate(name);
if (!nameStats.isSuccess()) {
throw new Exception();
}
return true;
}
...
验证器.java
public NameStats validate(String name)
{
NameStats nameStats = new NameStats();
// code goes here
return nameStats;
}
测试用例.java
...
@SpringBootTest
@RunWith(SpringRunner.class)
public class ImportFileOperationTest {
@Mock
Validator nameValidator;
@Mock
NameStats nameStats;
@InjectMocks
UserOperation operation;
@Test
public void ConnectorDelegate0Test() {
Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
Mockito.when(nameStats.isSuccess()).thenReturn(true);
operation.userOperation(restConsumerRequest);
}
}
...
错误:
对于上面的测试用例,我得到了NullPointerException。在跟踪时,我发现测试中的代码行下方返回 null 值。
Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
由于空值,当它尝试调用nameStats.isSuccess()
时,它会抛出空点异常,即使我嘲笑了对这个函数的响应true
。
问题:1. 我嘲笑的回答是否正确?2. 为什么模拟函数返回空对象?
更新:
测试用例.java
@SpringBootTest
@RunWith(SpringRunner.class)
public class ImportFileOperationTest {
@MockBean
Validator nameValidator;
NameStats nameStats;
@InjectMocks
@Resource
UserOperation operation;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void ConnectorDelegate0Test() {
nameStats = new nameStats();
Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
Mockito.when(nameStats.isSuccess()).thenReturn(true);
operation.userOperation(restConsumerRequest);
}
}
我尝试手动nameStats
创建对象,并期望validate
函数返回该对象,但它仍然返回null
。
任何帮助将不胜感激。
测试应为Mockito驱动或弹簧驱动。弹簧驱动的将具有@SpringBootTest
,并且@RunWith(SpringRunner.class)
类级别的注释和模拟将使用@MockBean
声明或使用Mockito.initMocks
显式实例化。模拟驱动的测试将具有@RunWith(MockitoJUnitRunner.class)
,并且模拟将声明为@Mock
和/或注入@InjectMocks
。请注意,当实例(如 NameStats
(在方法中使用 new
实例化时,注入无济于事。
显示的测试不必@SpringBootTest
,因此可以像这样编写为 Mockito 驱动的测试:
@RunWith(MockitoJUnitRunner.class)
public class ImportFileOperationTest {
@Mock
Validator nameValidator;
@InjectMocks
UserOperation operation;
@Test
public void connectorDelegateTest() {
NameStats nameStats = new NameStats();
nameStats.setStats(Stats.SUCCESS);
Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
operation.userOperation(restConsumerRequest);
}
类类型使用 @InjectMocks
,并且需要@Mock
用于该类中的所有关联属性。
例:
class Product {
ProductDetails productDetails;
}
class ProductDetails {
}
上述类的示例测试用例:
@SpringBootTest
@RunWith(SpringRunner.class)
public class ProductTest {
@Mock
ProductDetails productDetails;
@InjectMocks
Product product;
}
升级到 Spring Boot 2 后遇到了类似的问题。原因在这里解释 https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/ArgumentMatchers.html#any-java.lang.Class-
从 Mockito 2.1.0 开始,只允许 的非空实例,因此 null 不再是有效值。
所以 mock 返回 null 或空列表,因为调用是用 anyString()
设置的,并且传递的对象是 null。要匹配值或空值,请使用匹配器any()
。