使用EasyMock与线程

时间:2015-02-03 12:57:54

标签: java multithreading testng easymock

这似乎很容易,但我不知道该怎么做。我们有一个状态机,当触发转换时,事件通过EventManager类发送。这是在一个新线程中启动的,因为我们不希望在分发事件时阻塞当前线程。

假设我忘了在嘲笑时期待一个方法调用。测试现在应该失败了。但它并不是因为线程捕获了异常。我也不想传播期望,因为状态机在异常时停止。

public class TestStackoverflow {

    @Test
    public void test(){
        EventManager eventManager = EasyMock.createStrictMock(EventManager.class);
        EasyMock.replay(eventManager);
        MyClass myClass = new MyClass();
        myClass.executeStuff(eventManager);
        EasyMock.verify(eventManager);
    }

    private class MyClass{
        public void executeStuff(final EventManager eventManager){
            new Thread() {
                public void run() {
                    eventManager.sendEvent();
                }  
            }.start();
        }
    }

    interface EventManager{
        public void sendEvent();
    }
}

eventManager.sendEvent()抛出java.lang.AssertionError,但单元测试不会失败。

Exception in thread "Thread-0" java.lang.AssertionError:
  Unexpected method call EventManager.sendEvent():
        at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44)
        at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
        at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:97)
        at at.ac.TestStackoverflow$EventManager$$EnhancerByCGLIB$$cbb0f0e1.sendEvent(<generated>)
        at at.ac.TestStackoverflow$MyClass$1.run(TestStackoverflow.java:27)
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.58 sec

我如何测试这种情况?

2 个答案:

答案 0 :(得分:0)

即使异常确实传播回您的测试,它仍然可能无法正常工作,因为它看起来可能存在竞争条件。

例如,在您的测试中,&#34; executeStuff&#34;会启动线程,但它实际上可能没有机会直接运行。

如果主线程继续,它可能会进入&#34;验证&#34;在另一个线程有机会运行之前的声明。

如果稍微改变一下,以便在课堂外创建Thread,那么测试就会更容易。

然后,您可以使用UncaughtExceptionHandler来解决原始问题,例如......

public class TestStackoverflow {

    @Test
    public void test(){
        TestExceptionHandler exceptionHandler = new TestExceptionHandler();
        EventManager eventManager = EasyMock.createStrictMock(EventManager.class);
        EasyMock.replay(eventManager);

        // Create a MyClass - pass in the eventManager
        MyClass myClass = new MyClass(eventManager);

        // Create thread
        Thread thread = new Thread(myClass);
        thread.setUncaughtExceptionHandler(exceptionHandler);

        // Run your code
        thread.start();

        // WAIT FOR THREAD TO FINISH
        thread.join();

        // Check no exceptions were thrown
        exceptionHandler.verifyNoExceptions();
    }

    private class TestExceptionHandler implements UncaughtExceptionHandler {

        private Throwable e;

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            this.e = e;
        }

        public void verifyNoExceptions() {
            if(e != null) {
                throw new AssertionError("BOOM! Exception caught", e);
            }
        }

    }

    private class MyClass implements Runnable {
        private EventManager eventManager;

        public MyClass(EventManager eventManager) {
            this.eventManager = eventManager;
        }

        public void run(){
            eventManager.sendEvent();
        }
    }

    interface EventManager{
        public void sendEvent();
    }
}

答案 1 :(得分:0)

createStrictMock所做的是它创建了一个类的严格模拟,如果在Testclass中以特定顺序不需要在代码中调用的方法,则会抛出异常。这导致Unexpected method call例外(成功完成测试用例不应该首先出现例外情况)。

你需要创建一个漂亮的模拟,即Easymock.createNiceMock(EventManager.class);

这个例外应该解决

祝你好运!