我必须模拟下面的ParentChildDetail类 在下面的类中只有一个构造函数是可用的,它是参数化的构造函数。但构造函数正在调用initilase()方法。所以当模拟对象时,它再次调用initilase()方法,它会击中db。 但我必须手动为JUNIT测试创建数据
public class ParentChildDetail
{
private final String ALL_HQL = "hql query to fetch parent and child";
private Map<Integer, Set<Child>> parentChildMapping = null;
private Integer Id;
private DateTime date;
public ParentChildDetail( Integer Id, DateTime date ) throws HibernateException
{
this.Id = Id;
this.date = date;
initialise();
}
private void initialise() throws HibernateException
{
String[] paramNames =
{ "Id", "effectiveDate" };
Object[] paramValues =
{ Id, date };
List<Child> Childs = HibernateSession.query( ALL_HQL, paramNames, paramValues );
for ( Child child : Childs )
{
if ( parentChildCache.get( child.getParentId() ) == null )
{
Set<Child> val = new HashSet<>();
val.add( child );
parentChildCache.put( child.getParentId(), val );
}
else
{
parentChildCache.get( child.getParentId() ).add( child );
}
}
}
public Map<Integer, Set<Child>> getParentChildCache()
{
return parentChildCache;
}
public void setParentChildCache( Map<Integer, Set<Child>> parentChildCache )
{
this.parentChildCache = parentChildCache;
}
}
但是在模拟参数化构造函数时再次调用initialise()
Here the sample code I am writing to mock
Method initialize=ParentChildDetail.class.getDeclaredMethod( "initialise", noparams );
Object[] args={1,new DateTime(new Date( "01/01/2017" ))};
Constructor<ParentChildDetail> c=ParentChildDetail.class.getConstructor(Integer.class,org.joda.time.DateTime.class);
ConstructorArgs constructorArgs = new ConstructorArgs(c,args);
ParentChildDetail p= PowerMock.createMock( ParentChildDetail.class, constructorArgs,initialize );
在最后一行低于错误
java.lang.RuntimeException: Failed to instantiate mock calling constructor: Exception in constructor
at org.easymock.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:219)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:129)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:114)
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2220)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
at org.powermock.api.easymock.PowerMock.createMock(PowerMock.java:108)
at com.subex.rocps.routingratecalculator.ParentChildTest.getTrnIdOperatorMDLMap(ParentChildTest.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalStateException
at com.subex.spark.database.hibernate.util.HibernateSession.checkInitialised(HibernateSession.java:288)
at com.subex.spark.database.hibernate.util.HibernateSession.getSessionFactory(HibernateSession.java:254)
at com.subex.spark.database.hibernate.util.HibernateSession.query(HibernateSession.java:298)
at com.subex.rocps.routingratecalculator.util.ParentElementCacheCreator.initialise(ParentElementCacheCreator.java:41)
at com.subex.rocps.routingratecalculator.util.ParentElementCacheCreator.<init>(ParentElementCacheCreator.java:31)
at com.subex.rocps.routingratecalculator.util.ParentElementCacheCreator$$EnhancerByCGLIB$$ba31f8d9.<init>(<generated>)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.easymock.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:207)
... 29 more
答案 0 :(得分:0)
正如评论者所说,调用数据访问层作为构建类的副作用的方法可能是反模式。无论如何,它使得单元测试很难。在这种情况下出现困难是因为ParentChildDetail()
调用ParentChildDetail.initialise()
而HibernateSession.query()
调用ParentChildDetail
,因为这是一个静态方法,测试它有点棘手。
以下测试用例使用EasyMock(因为这是您的问题标记的)和PowerMock以便于实例化@RunWith(PowerMockRunner.class)
@PrepareForTest(HibernateSession.class)
public class ParentChildDetailTest {
@Test
public void testSomething() {
PowerMock.mockStatic(HibernateSession.class);
Integer id = 1234;
DateTime date = new DateTime();
// not sure what you want to retrieve here, maybe nothing, maybe some particular children so
// that you can test the behaviour of the initialise() method
List<Child> children = new ArrayList<>();
expect(HibernateSession.query(anyString(), (String[]) anyObject(), (Object[]) anyObject()))
.andReturn(children);
PowerMock.replay(HibernateSession.class);
ParentChildDetail parentChildDetail = new ParentChildDetail(id, date);
// parentChildDetail has now been successfully constructed/initialised and it is available for use in your test ...
}
}
:
Util myUtil = DaggerMyComponent.builder().withAddress(txtAddress.getText()).build().getComponent().getUtil();
此代码适用于EasyMock v3.4,PowerMock v1.6.1 +和Junit 4.12
使用PowerMock here进行模拟的详细信息。
有关集成JUnit,EasyMock和PowerMock here的详细信息。