使用PowerMock防止静态初始化



因此,我的课程中有一个静态变量。我试图用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);
  }
}

一些点

  1. 由于EntityManager不是@Aurowired,因此不需要@InjectMocks
  2. 由于您希望调用ClassUnderTest::methodUnderTest下的代码,因此请勿在@PrepareForTest中使用classundertest
  3. 不做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

并删除ClassUnderTestmockStatic

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。

相关内容

  • 没有找到相关文章

最新更新