Alaycı sistem sınıfı sırasında Mockito + PowerMock LinkageError


166

Böyle bir kod pasajı var:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Thread.class})
public class AllMeasuresDataTest {

@Before
public void setUp() throws Exception {
}

@Test
public void testGetMeasures() {
    AllMeasuresData measure = new AllMeasuresData();
    assertEquals(measure.getMeasures(), null);
    HashMap<String, Measure> map = new HashMap<String, Measure>();
    measure.setMeasures(map);
    assertEquals(measure.getMeasures(), map);
    measure.setMeasures(null);
    assertEquals(measure.getMeasures(), null);
}

@Test
public void testAllMeasuresData() throws IOException {
    ClassLoader loader = PowerMockito.mock(ClassLoader.class);
    Thread threadMock = PowerMockito.mock(Thread.class);
    Vector<URL> vec = new Vector<URL>();
    Mockito.when(loader.getResources("measure")).thenReturn(vec.elements());
    Mockito.when(threadMock.getContextClassLoader()).thenReturn(loader);
    PowerMockito.mockStatic(Thread.class);
    Mockito.when(Thread.currentThread()).thenReturn(threadMock);
        ...
    }
}

Bu testleri çalıştırırken:

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"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:201)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:149)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.initializeMBean(ProtocolImpl.java:247)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.<init>(ProtocolImpl.java:237)
at org.codecover.instrumentation.java.measurement.ProtocolImpl.getInstance(ProtocolImpl.java:185)
at measure.CodeCoverCoverageCounter$6ya5ud0ow79ijrr1dvjrp4nxx60qhxeua02ta2fzpmb1d.<clinit>(MeasureCalculatorsHolder.java:146)
at measure.MeasureCalculatorsHolder.<clinit>(MeasureCalculatorsHolder.java:17)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:188)
at javassist.runtime.Desc.getClassObject(Desc.java:43)
at javassist.runtime.Desc.getClassType(Desc.java:152)
at javassist.runtime.Desc.getType(Desc.java:122)
at javassist.runtime.Desc.getType(Desc.java:78)
at algorithm.AllMeasuresDataTest.testGetMeasures(AllMeasuresDataTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTestInSuper(PowerMockJUnit49RunnerDelegateImpl.java:116)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTest(PowerMockJUnit49RunnerDelegateImpl.java:77)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.codecover.juniteclipse.runner.EclipseTestRunner.main(EclipseTestRunner.java:40)

Bunu nasıl önleyebilirim biliyor musunuz? Belki böyle bir kod parçası alay etmek için başka bir yolu var:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
...
Enumeration<URL> resources = classLoader.getResources(path);

Ne yapmaya çalışıyorsun? Ve neden?
NilsH

İlk test getters ve setters testi, orada yapıcı çağırıyorum (ve orada istisna oluşur). İkincisi yapıcı testidir. Üçüncü kod snippet'inde hangi kaynak numaralandırmasının içerdiğini denetlemek istiyorum.
Wojciech Reszelewski

1
Her şeyden önce, testlerinizin uygulamanızla çok sıkı bir şekilde bağlantılı olduğunu düşünüyorum. Tecrübe ile bu kırılgan testlere yol açacaktır. Tercihen, testlerinizi yazarken "kara kutu" düşünmek istersiniz. "Bu kod parçası bunu nasıl yapıyor" yerine "Bu kod parçası ne yapmalı". İkincisi, sadece bir dizi kaynak oluşturmaktan daha iyi olacağını ve Java çalışma zamanının sınıf yüklemesinin kendisiyle ilgilenmesine izin vereceğinizi düşünüyorum.
NilsH

Test senaryolarında olduğu gibi çeşitli kaynak grupları oluşturmak mümkün mü?
Wojciech Reszelewski

Elbette. Sizin için en kolayı muhtemelen kaynakların adını parametrelendirmektir. Daha sonra testlerinize farklı kaynak adları aktarabilirsiniz.
NilsH

Yanıtlar:


408

Bu ek açıklamayı Test sınıfınıza eklemeyi deneyin:

@PowerMockIgnore("javax.management.*")

Benim için çalıştı.


2
Hassasiyet * "Test Sınıfınıza". Basit ve kullanışlı cevap!
15:09

3
Bu kod veya yapılandırma ile de yapılabilir mi? Bunu yapmanın bir yolunu bulamadım. Yüzlerce testimiz var ... hepsini ayarlayamıyorum.
Frederic Leitenberger

1
@FredericLeitenberger aşağıdaki cevabımı gör
user3474985

2
Bu düzeltmenin amacını ve anlamını da açıklayabilir misiniz? Bu hattı kullanarak PowerMockito'ya hangi talimatları veriyoruz?
Swapnil B.

33

Burada kabul edilen yanıta benzer şekilde, SSL ile ilgili tüm sınıfları hariç tutmak zorunda kaldım:

@PowerMockIgnore({"javax.management.*", "org.apache.http.conn.ssl.*", "com.amazonaws.http.conn.ssl.*", "javax.net.ssl.*"})

Bunu sınıfımın en üstüne eklemek hatayı çözdü.


5
Hala daha fazla yol eklemeye ihtiyacım vardı ama sen hayatımı kurtardın @PowerMockIgnore({"javax.management.*", "org.apache.http.conn.ssl.*", "com.amazonaws.*", "javax.net.ssl.*","com.sun.*"})
Francisco López-Sancho

Com.sun hakkında bilmek de güzel.
Jason D

1
Aşağıdakilere ihtiyacım vardı: @PowerMockIgnore ({"javax.management. *", "Javax.crypto. *"})
Kristof Neirynck

2
Bu beni kurtardı: @PowerMockIgnore ({"javax.management. *", "Org.apache.http. *", "Com.amazonaws.http.conn.ssl. *", "Javax.net.ssl. *" , "com.sun. *", "javax.xml. *", "javax.crypto. *"})
Fayaz Ahmed

26

Classloader çakışması, şunu kullanın:@PowerMockIgnore("javax.management.*")

Sahte sınıf yükleyicinin yüklenmemesine izin verin javax.*. .


Kullandıktan sonra @PowerMockIgnore("javax.management.*")test sınıfı tek başına iyi çalışır. Ama çalışan Junit testbu konuda paketin var Failed to load ApplicationContexthatası. org.apache.catalina.LifecycleException: A child container failed during startve bunun gibi.
niaomingjian

8

Bu biraz eski bir konu olabilir, ama ben de bu problemle karşılaştım. Powermock'un aynı pakette aynı ada sahip 2 sınıf (farklı bağımlılıklar üzerinde) olduğunu öğrendiğinde, bazı java sürümlerinin powermockito'yu işleyemeyeceği ortaya çıkıyor.

Java 7_25 sürümünden daha yüksek herhangi bir sürümde bu hatayı verir.


2
"Java 7_25 sürümünden daha yüksek herhangi bir sürümde bu hatayı verir."
Kajal Sinha

Ne anlama geliyor: "powermockito ile baş edemiyor"? Ek açıklama ile yok saymanın yanı sıra bununla başa çıkmanın herhangi bir yolu var mı?
Hat

Uzun zaman önce, ama aynı tür pakette aynı adı taşıyan 2 sınıf olmadığından emin olarak sıraladık. Tabii ki, bağımlı olduğunuz 2 kütüphaneniz varsa ve orada ikamet ediyorlarsa ... bu zor olacak. Bu sorunun bu arada çözülüp çözülmediğini bilmiyorum.
Rens Groenveld

3

Sistem sınıflarını taklit etmek için, testin hedefi olan sınıfı hazırlayın, değil Thread.class. PowerMock'un enstrümanı kullanmasının bir yolu yoktur, Thread.classçünkü JVM başlangıcı sırasında gereklidir - PowerMock enstrümanın yapabilmesi için çok önce.

Enstrümantasyonun çalışma şekli, bir sınıf yüklendikten sonra artık girilemez.

PowerMock wiki'sine bakın .


3

PowerMock 1.7.0'da projenizin sınıfyoluna kullanıcı tanımlı bir global yapılandırma eklenebilir. PowerMockConfig

org/powermock/extensions/configuration.properties

Özellikler dosyasına aşağıdaki gibi bir satır eklemeniz yeterlidir:

powermock.global-ignore=javax.management.*

Bu, projenizdeki tüm sınama sınıfları için hatayı giderir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.