Java 模拟时junit中出现错误
我是Junit新手,下面是我正在运行的Junit代码Java 模拟时junit中出现错误,java,unit-testing,junit,mocking,powermock,Java,Unit Testing,Junit,Mocking,Powermock,我是Junit新手,下面是我正在运行的Junit代码 package com.de.base.util.general; import static org.junit.Assert.*; import static org.mockito.Mockito.when; import java.util.HashMap; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import o
package com.de.base.util.general;
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;
@RunWith(MockitoJUnitRunner.class)
public class JReportUtilTest {
@InjectMocks
ReportUtil w_res = new ReportUtil();
@Mock
CollectionUtil w_util;
@Test
public void test_removeHashedSettings() throws Exception {
HashMap<String ,String> w_abc = new HashMap<String,String>();
w_abc.put("abc","89");
//CollectionUtil mock = org.mockito.Mockito.mock(CollectionUtil.class);
//PowerMockito.mockStatic(CollectionUtil.class,w_abc);
when(w_util.createHashMap("abc:89", ":")).thenReturn(w_abc);
assertEquals("abc:89:",ReportUtil.removeHashedSettings("1", "abc:89", ":"));
}
}
下面是CollectionUtil中createHashMap的代码,我必须对其进行模拟
public static HashMap<String, String> createHashMap(String a_NameValStr, String a_Delim)// throws Exception
{
HashMap<String, String> w_KeyVal = new HashMap<String, String>();
if (LOGGER.isInfoEnabled()) LOGGER.info("CollectionUtil:createHashMap:Hashing string: "+ a_NameValStr );
if(a_NameValStr == null) return w_KeyVal;
StringTokenizer w_StrTkn = new StringTokenizer(a_NameValStr, a_Delim);
if( w_StrTkn.countTokens() == 0 || (w_StrTkn.countTokens()%2) != 0 )
{
LOGGER.warn("CollectionUtil:createHashMap:Invalid number of tokens to hash: "+ a_NameValStr+":"+w_StrTkn.countTokens() );
return w_KeyVal;
}
while (w_StrTkn.hasMoreTokens()) w_KeyVal.put( w_StrTkn.nextToken(), w_StrTkn.nextToken());
System.out.println(w_KeyVal);
return w_KeyVal;
}
我正在使用mockito-all-1.10.19.jar、powermock-api-mockito-1.6.6.jar、powermock-core-1.6.6.jar、powermock-module-junit4-1.6.6.jar
有人能帮我解决这个问题吗?您不使用PowerMock runner:
@RunWith(PowerMockRunner.class)
Mockito无法模拟静态方法,但PowerMock可以
您应该使用静态方法模拟该类:
PowerMockito.mockStatic(CollectionUtil.class);
无论如何,更好的设计是用实例方法取代静态方法。静态方法不是自然可测试的,并且强制创建复杂且不可读的解决方法。
例如,查看测试简单类所需的依赖项组合的复杂性。
您应该保持使用静态方法作为助手,这些方法不执行域的核心逻辑,也不需要模拟 当这些方法执行域的核心逻辑时,就像
createHashMap()静态方法
的情况一样,您很可能需要对其进行模拟,以避免在测试期间在依赖类之间产生副作用正如您所注意到的:模拟静态方法非常笨拙,因为静态方法实际上不是设计为被重写的。
此外,对于域的核心逻辑,您应该能够利用OOP(继承性、多态性、设计模式等),如何用静态方法实现它
对于遗留代码,我们不能真的不更改,这是可以接受的,但除此之外,不可以,您应该重构代码。以下是我的工作代码:
import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(CollectionUtil.class)
public class TestHarnesTest {
@InjectMocks
TestHarnes w_res = new TestHarnes();
@Before
public void before() {
PowerMockito.mockStatic(CollectionUtil.class);
}
@Test
public void test_removeHashedSettings() throws Exception {
HashMap<String, String> w_abc = new HashMap<String, String>();
w_abc.put("abc", "89");
// CollectionUtil mock = org.mockito.Mockito.mock(CollectionUtil.class);
// PowerMockito.mockStatic(CollectionUtil.class,w_abc);
PowerMockito.when(CollectionUtil.createHashMap(Mockito.eq("abc:89"), Mockito.eq(":"))).thenReturn(w_abc);
assertEquals("abc:89:", TestHarnes.removeHashedSettings("1", "abc:89", ":"));
}
}
CollectionUtil是最终类吗?它不是最终类您试图在
CollectionUtil
中模拟的方法是静态的,因此您需要在类上使用@RunWith(PowerMockRunner.class)
和@PrepareForTest(CollectionUtil.class)
。此外,您还需要调用PowerMockito.mockStatic(CollectionUtil.class)代码>如上所述,我正在使用3个powermock JAR。但在实现您的代码时,我仍然会遇到此错误。无法解析类型org.powermock.api.support.membermodification.MemberModifier。它是从必需的类文件中间接引用的。如果缺少依赖项,或者IDE未刷新。当我说我强制创建复杂的解决方法时:看看测试简单类所需的混合依赖的复杂性。对于没有状态的实用程序类,为什么使用静态方法不是一个好的设计?它保存了对象的创建,从而产生了更短、更干净的生产代码。@Yoav Gur我同意静态方法是一个助手,它不执行域的核心逻辑,因此您不需要模拟它。当它像这里一样执行域的核心逻辑时,您可能需要模拟它,以避免在测试期间在依赖类之间产生副作用。而您模拟的静态方法不是更短的更干净的代码。此外,对于域的核心逻辑,您应该能够利用OOP(继承性、多态性、设计模式等),如何用静态方法实现它?我在PowerMockito.mockStatic(CollectionUtil.class)中遇到了错误;错误为:-无法解析类型org.powermock.api.support.membermodification.MemberModifier。它是从required.class文件间接引用的。您的CollectionUtil类是什么?它来自哪个框架?感谢您的帮助。但是当我运行您的代码时,生成了以下错误。java.lang.NoClassDefFoundError:org/powermock/api/mockito/expectation/With或WithioutExpectedArguments
PowerMockito.mockStatic(CollectionUtil.class);
import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(CollectionUtil.class)
public class TestHarnesTest {
@InjectMocks
TestHarnes w_res = new TestHarnes();
@Before
public void before() {
PowerMockito.mockStatic(CollectionUtil.class);
}
@Test
public void test_removeHashedSettings() throws Exception {
HashMap<String, String> w_abc = new HashMap<String, String>();
w_abc.put("abc", "89");
// CollectionUtil mock = org.mockito.Mockito.mock(CollectionUtil.class);
// PowerMockito.mockStatic(CollectionUtil.class,w_abc);
PowerMockito.when(CollectionUtil.createHashMap(Mockito.eq("abc:89"), Mockito.eq(":"))).thenReturn(w_abc);
assertEquals("abc:89:", TestHarnes.removeHashedSettings("1", "abc:89", ":"));
}
}
public class TestHarnes {
public static String removeHashedSettings(final String key, final String a_settings, final String deilimiter) throws Exception {
if (!(key != null && key.trim().length() > 0)) {
return a_settings;
}
if (!(a_settings != null && a_settings.trim().length() > 0)) {
return a_settings;
}
HashMap hSettings = CollectionUtil.createHashMap(a_settings, deilimiter);
hSettings.remove(key);
return getSettingFromHash(hSettings, deilimiter);
}
private static String getSettingFromHash(final HashMap hSettings, final String deilimiter) {
return "";
}
}