因此,我的课程中有一个静态变量。我试图用PowerMockito嘲笑它,但我遇到了错误。
public class ClassUnderTest{
private static EntityManager em = AppEntityManager.createEntityManager();
public static String methodUnderTest(){
// this method dosent use EntityManager em
}
}
我的测试课是这样的:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ AppEntityManager.class, ClassUnderTest.class })
public class ClassUnderTestTest {
@Mock
private EntityManager emMock;
@InjectMocks
private ClassUnderTest feMock;
static ClassUnderTest fe = new ClassUnderTest();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
PowerMockito.mockStatic(ClassUnderTest.class);
PowerMockito.mockStatic(AppEntityManager.class);
Mockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);
String s = ClassUnderTest.methodUnderTest(myParams);
// assertEquals(prams[i][1], s);
System.out.println(s);
}
}
错误是
Feb 22, 2018 9:37:31 AM oracle.jdbc.driver.OracleDriver registerMBeans
SEVERE: Error while registering Oracle JDBC Diagnosability MBean.
java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"
你能告诉我我要在哪里出错吗?我只想测试methodUnderTest()
,所以有一种方法可以防止EntityManager em
的静态初始化?
此代码对我有用
@RunWith(PowerMockRunner.class)
@PrepareForTest({ AppEntityManager.class})
public class ClassUnderTestTest {
@Mock
private EntityManager emMock;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
PowerMockito.mockStatic(AppEntityManager.class);
Mockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);
String s = ClassUnderTest.methodUnderTest(myParams);
// assertEquals(prams[i][1], s);
}
}
一些点
- 由于EntityManager不是
@Aurowired
,因此不需要@InjectMocks
。 - 由于您希望调用
ClassUnderTest::methodUnderTest
下的代码,因此请勿在@PrepareForTest
中使用classundertest - 不做
PowerMockito.mockStatic(ClassUnderTest.class);
说了所有这些。您应该认真考虑重构代码,以最大程度地减少(如果可能消除(所有静态方法和字段。
通过练习更好的设计原理。
你能告诉我我要在哪里做错了吗?
紧密耦合到该静态依赖性现在使您的代码难以测试。
使通过构造函数注入的显式依赖性。
public class ClassUnderTest{
private EntityManager em;
public ClassUnderTest(EntityManager em) {
this.em = em;
}
public String methodUnderTest(){
// this method dosent use EntityManager em
}
}
现在测试时,您可以简单地通过NULL EntityManager
,因为它在测试中不需要。
使用PowerMockito.when
代替Mockito.when
。
并删除ClassUnderTest
的mockStatic
。
so:
PowerMockito.mockStatic(AppEntityManager.class);
PowerMockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);
正如许多其他已经提到的其他已经提到的,您真的不应该使用静态依赖性,因为它会导致这种可怕的测试设计。
但是,如果您无法更改测试的代码,则可以通过反射注入EntityManager:
public class ClassUnderTestTest {
private ClassUnderTest classUnderTest;
@BeforeEach
public void setUp() throws Exception {
final Field entityManagerField;
classUnderTest = new ClassUnderTest();
//Use getDeclaredField(...) since field is private
entityManagerField = classUnderTest.getClass()
.getDeclaredField("em");
//Set accessible since field is private
entityManagerField.setAccessible(true);
entityManagerField.set(classUnderTest,
Mockito.mock(EntityManager.class));
}
@Test
public void test() {
String s = classUnderTest.methodUnderTest();
// assertEquals(prams[i][1], s);
System.out.println(s);
}
}
class ClassUnderTest{
private static EntityManager em;
public String methodUnderTest(){
// this method dosent use EntityManager em
// but solution don´t care
return "";
}
}
这样,您也可以关闭Pandora的Box aka PowerMock,然后继续进行基本的Unitesting and Mocking。