在另一个方法中模拟一个方法

时间:2020-08-29 18:22:00

标签: java unit-testing intellij-idea mocking mockito

这是我正在测试的方法,并且我正在使用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块:如果我调用此方法,我将模拟该类的一个实例并在该模拟对象上调用该方法,但由于不是我调用此方法,而是由该方法在下面的方法调用测试,我该如何正确模拟它?

大家好!

1 个答案:

答案 0 :(得分:2)

如果您可以使用Powermock来mock the creation of new objects,并且您不能或不想重构现有代码,则可以使用。使用Powermock并非没有缺点,而是对这种情况和其他情况(静态类/方法以及私有/受保护的类/方法/字段)进行更精细控制的有效方法。