这是我正在测试的方法,并且我正在使用Mockito进行模拟:
/**
* Sync get all children under single zk node.
*
* @param zk
* zookeeper client
* @param node
* node path
* @return direct children
* @throws InterruptedException
* @throws IOException
*/
public static List<String> getChildrenInSingleNode(final ZooKeeper zk, final String node, long zkOpTimeoutMs)
throws InterruptedException, IOException, KeeperException.NoNodeException {
final GetChildrenCtx ctx = new GetChildrenCtx();
getChildrenInSingleNode(zk, node, new GenericCallback<List<String>>() {
@Override
public void operationComplete(int rc, List<String> ledgers) {
synchronized (ctx) {
if (Code.OK.intValue() == rc) {
ctx.children = ledgers;
}
ctx.rc = rc;
ctx.done = true;
ctx.notifyAll();
}
}
});
synchronized (ctx) {
long startTime = System.currentTimeMillis();
while (!ctx.done) {
try {
ctx.wait(zkOpTimeoutMs > 0 ? zkOpTimeoutMs : 0);
} catch (InterruptedException e) {
ctx.rc = Code.OPERATIONTIMEOUT.intValue();
ctx.done = true;
}
// timeout the process if get-children response not received
// zkOpTimeoutMs.
if (zkOpTimeoutMs > 0 && (System.currentTimeMillis() - startTime) >= zkOpTimeoutMs) {
ctx.rc = Code.OPERATIONTIMEOUT.intValue();
ctx.done = true;
}
}
}
if (Code.NONODE.intValue() == ctx.rc) {
throw new KeeperException.NoNodeException("Got NoNode on call to getChildren on path " + node);
} else if (Code.OK.intValue() != ctx.rc) {
throw new IOException("Error on getting children from node " + node);
}
return ctx.children;
}
这是我的测试课:
@RunWith(value= Parameterized.class)
public class ZkUtilsGetChildrenTest {
private boolean expectedResult;
private ZooKeeper zkc ;
private String path;
private long timeout;
private static List<String> paths = Arrays.asList("/ledgers/000/000/000/001", "/ledgers/000/000/000/002",
"/ledgers/000/000/000/003");
private static List<String> childPaths = Arrays.asList("001", "002", "003");
// ZooKeeper related variables
private static ZooKeeperUtil zkUtil = new ZooKeeperUtil();
@Mock
ZkUtils.GetChildrenCtx mocked = mock(ZkUtils.GetChildrenCtx.class) ;
@BeforeClass
public static void setUp() throws Exception {
zkUtil.startCluster();
ZooKeeper initializerZkc = new ZooKeeper(zkUtil.getZooKeeperConnectString(), 10000, null);
for (String path : paths ){
ZkUtils.createFullPathOptimistic(initializerZkc, path, "data".getBytes() , ZooDefs.Ids.OPEN_ACL_UNSAFE ,
CreateMode.CONTAINER);
}
}
@AfterClass
public static void tearDown() throws Exception {
zkUtil.killCluster();
}
@Parameterized.Parameters
public static Collection<Object[]> getTestParameters() throws IOException {
return Arrays.asList(new Object[][]{
{false , "null" , "/ledgers/000/000/000/004" , 0},
{true , "new" , "/ledgers/000/000/000" , 1000 },
{false , "wrong" , "/ledgers/000/000/000/00b" , -1},
{false , "new" , "/ledgers/000/000/00b" , 0 },//aggiunto per migliorare statement e branch coverage
{false , "new" , "/ledgers/000/000/003" , 1 },//aggiunto per migliorare statement e branch coverage
{false , "mock" , "/ledgers/000/000" , 1000 },//aggiunto per migliorare statement coverage
});
}
public ZkUtilsGetChildrenTest(boolean expectedResult ,String zkc , String path , long timeout) throws IOException {
if(zkc == "null"){
this.zkc = null;
}else if( zkc == "wrong"){
this.zkc = new ZooKeeper("wrongString", 10000, null);
}else if(zkc == "new"){
this.zkc = new ZooKeeper(zkUtil.getZooKeeperConnectString(), 10000, null);
}else if(zkc == "mock"){
//TODO MOCK THE INNER METHOD
this.zkc = new ZooKeeper(zkUtil.getZooKeeperConnectString(), 10000, null);
when(mocked).thenThrow(new InterruptedException());
}
this.expectedResult = expectedResult;
this.path = path;
this.timeout = timeout;
}
@Test
public void testGetChildrenInSingleNode() {
boolean realResult;
try {
List<String> children = ZkUtils.getChildrenInSingleNode(zkc, path, timeout);
assertThat(children, is(childPaths));
} catch (Exception e) {
realResult = false;
e.printStackTrace();
assertEquals(expectedResult, realResult);
}
}
}
我想问你如何模拟ctx.wait(zkOpTimeoutMs> 0?zkOpTimeoutMs:0);这样我就可以触发遵循此语句的catch块:如果我调用此方法,我将模拟该类的一个实例并在该模拟对象上调用该方法,但由于不是我调用此方法,而是由该方法在下面的方法调用测试,我该如何正确模拟它?
大家好!
答案 0 :(得分:2)
如果您可以使用Powermock来mock the creation of new objects,并且您不能或不想重构现有代码,则可以使用。使用Powermock并非没有缺点,而是对这种情况和其他情况(静态类/方法以及私有/受保护的类/方法/字段)进行更精细控制的有效方法。