Reputation: 27
So I have a static variable in my class under test. I have tried to mock it With Powermockito but I am getting error.
public class ClassUnderTest{
private static EntityManager em = AppEntityManager.createEntityManager();
public static String methodUnderTest(){
// this method dosent use EntityManager em
}
}
My test class is like this:
@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"
Can you tell me where I am going wrong?
I just want to test methodUnderTest()
and so is there a way I can prevent that static initialization of EntityManager em
?
Upvotes: 1
Views: 4505
Reputation: 116
As many other already mentioned, you really shouldn´t use static dependency’s as it leads to that kind of horrible testable design.
However, if you cannot change the code under test, you could inject the EntityManager via reflections:
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 "";
}
}
That way you can also close Pandora´s Box aka PowerMock and continue with basic UnitTesting and mocking.
Upvotes: 0
Reputation: 27068
This code works for me
@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);
}
}
Some points
@Aurowired
, there is no need for @InjectMocks
. ClassUnderTest::methodUnderTest
to be called, don't use ClassUnderTest in @PrepareForTest
PowerMockito.mockStatic(ClassUnderTest.class);
Having said all of these. You should seriously consider refactoring your code to minimize(if possible eliminate) all static methods and fields.
Upvotes: 1
Reputation: 12215
Use PowerMockito.when
instead of Mockito.when
.
And remove mockStatic
of ClassUnderTest
.
So:
PowerMockito.mockStatic(AppEntityManager.class);
PowerMockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);
Upvotes: 0
Reputation: 247333
By practicing better design principles.
Can you tell me where I am going wrong?
Tightly coupling to that static dependency is now making your code difficult to test.
Make that an explicit dependency that is injected via constructor.
public class ClassUnderTest{
private EntityManager em;
public ClassUnderTest(EntityManager em) {
this.em = em;
}
public String methodUnderTest(){
// this method dosent use EntityManager em
}
}
Now when testing you can simply pass a null EntityManager
since it is not needed in the test.
Upvotes: 1