为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 JMockit 中正确模拟私有 ExecutorService 的提交方法

如何在 JMockit 中正确模拟私有 ExecutorService 的提交方法

江户川乱折腾 2023-06-28 15:31:38
我有一个包含私有 ExecutorService 实例的类。在类中,我有一个方法运行提交方法并捕获 RejectedExecutionException。但是,我在模拟 ExecutorService 实例以引发异常以便我可以完成测试覆盖率时遇到了麻烦。我正在使用 JMockit 1.45。我已经浏览过 JMockit 教程和其他网站;无论我使用@Mocked、@Capturing,还是创建一个新的假类,它似乎都不起作用。// Implemented Class:public class TaskRegister {    private ExecutorService executor;    public TaskRegister() {        this.executor = Executors.newFixedThreadPool(5);    }    public void executeTask(Runnable task) {        try {            this.executor.submit(task);        } catch (RejectedExecutionException e) {            System.out.println(e.getMessage);        }    }}// Unit Test Class:public class TestTaskRegister {    @Tested    private TaskRegister tested;    private static int counter;    @Test // this works    public void runNormalTask() throws InterruptedException {        counter = 0;        Runnable mockTask = new Runnable() {            counter++;        }        tested.executeTask(mockTask);        Thread.sleep(100); // Allow executor to finish other thread.        assertEquals(1, counter);    }    @Test // this doesn't work, will have missing invocation error.    public void throwsError (@Capturing ExecutorService executor) throws InterruptedException {        counter = 0;        // somehow the tested class still runs the actual executor         // and not the mocked one.        new Expectations() {{             executor.submit((Runnable) any);             result = new RejectedExecutionException();        }};        Runnable mockTask = new Runnable() {            // some task        }        tested.executeTask(mockTask);        Thread.sleep(100);        assertEquals(0, counter);    }}我希望 @Capturing 拦截真正的执行程序实现并在调用 executor.submit 时抛出异常,但它没有这样做。
查看完整描述

2 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

模拟的@Capturing成本可能很高,并且在某些情况下可能会导致意外结果,因此(目前)所有java.*类都被排除在外。所以,java.util.concurrent.ThreadPoolExecutor在这个测试中不会被嘲笑(它可以与@Mocked)。

实际上,RejectedExecutionException异常永远不会发生(至少不会发生ThreadPoolExecutor- 可能只会发生ForkJoinPool)。所以,这个测试不值得付出努力。事实上,由于该异常是一个,RuntimeException您可以简单地catch完全删除该块。

这是(滥用)模拟库发生的坏事之一:人们有时使用它们来测试不可能的情况,因此编写无用的测试。


查看完整回答
反对 回复 2023-06-28
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您可以使用Executorin 参数创建一个新的构造函数。

因此,您的类将更加可配置(因为目前您只能使用一种执行器),并且您将能够通过使用模拟执行器手动实例化该类来测试该类。


public class TaskRegister {


    private ExecutorService executor;


    public TaskRegister(ExecutorService executor) {

        this.executor = executor;

    }


    public TaskRegister() {

        this(Executors.newFixedThreadPool(5));

    }


    public void executeTask(Runnable task) {

        try {

            this.executor.submit(task);

        } catch (RejectedExecutionException e) {

            System.out.println(e.getMessage);

        }

    }

}


查看完整回答
反对 回复 2023-06-28
  • 2 回答
  • 0 关注
  • 146 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信