java - JUnit +泛型抽象类测试库:我的测试中总是出现nullpointerexception,抽象方法中没有进行字段初始化
问题描述
在 Jave EE 应用程序中,我想为内存数据库集成测试创建一个基础测试,以初始化EntityManagerFactory
和EntityManager
. 此外,要测试的服务 bean 未确定,所以我将其设为通用。
我有:
package xxxxx;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.spy;
/**
* T: the service bean class to test
*/
public abstract class H2DBIntTestBase<T> {
protected EntityManager realEntityManager;
protected static EntityManagerFactory factory;
protected T serviceBean;
public abstract void setServiceBean();
public abstract String getPUName();
@Before
public void setup() {
// as we cannot statically get class name in @BeforeClass of super class, we have to do
// it like this. We don't care repetitive creation, as they are the same one, so we don't
// guard it with sychronization/double check.
if (factory == null) {
factory = Persistence.createEntityManagerFactory(getPUName());
}
realEntityManager = factory.createEntityManager();
EntityManager spy = spy(realEntityManager);
setServiceBean();
try {
// inject the real entity manager, instead of using mocks
Field entityManagerField = serviceBean.getClass().getDeclaredField("entityManager");
entityManagerField.setAccessible(true);
entityManagerField.set(serviceBean, spy);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new AssertionError("should not reach here");
}
}
@After
public void teardown() {
realEntityManager.close();
}
}
而且,在我的具体 int 测试中:
@RunWith(MockitoJUnitRunner.class)
public class MyServiceBeanIntTest extends H2DBIntTestBase<MyServiceBean> {
private Query<String> inputQuery;
@Override
public void setServiceBean() {
super.serviceBean = new SubscriptionHistoryPersistenceServiceBean();
}
@Override
public String getPUName() {
return serviceBean.getClass().getName();
}
@Before
public void setup() {
inputQuery = new Query<>();
... // other stubbings
}
@Test
public void test1() {
try {
// when
List<SubscriptionHistory> actual = serviceBean.doSth(inputQuery, Enum.TypeA);
// <----------- here serviceBean is always null, why?
// then
// assertions
} catch (DataLookupException e) {
throw new AssertionError("should not reach here");
}
}
}
但是,我在测试中总是有 NPE,首先在 . @After
,然后在我的@Test
.
为什么我serviceBean
的没有初始化?超级测试不应该在子类@BeforeClass
之前运行吗?@Before
模拟:org.mockito:mockito-core:1.10.19
JUnit:junit:junit:4.11
我没有使用 Spring/Spring Boot。
解决方案
为什么我的 serviceBean 没有初始化?
因为你已经setup()
在子类中被覆盖了。
要么给子类(或超类)setup()
一个不同的名字,要么从子类中调用超类。
推荐阅读
- boto3 - 为初始 AWS 应用程序自动扩展添加延迟
- clojure - Clojure - 宏扩展如何在“some”函数内部工作
- python - 从具有重复文件名的不同目录导入文件
- wordpress - WP Rest API 通过带有特殊字符的 slug 发布(例如:!&')
- firebase - 使用 Firebase Crashlytics 获取发生崩溃的用户的 ID
- c++ - 如何递归地将十六进制转换为十进制
- python - 如何摆脱相互更新小部件的循环?
- python - Selenium-Python:无法清除 chrome 浏览器缓存
- linux - 如何存储已经通过管道的命令的输出
- python - 如何在python中编写多个json文件?