com.crossbusiness.resiliency.aspect.AnnotationTimeoutAspectTest.java Source code

Java tutorial

Introduction

Here is the source code for com.crossbusiness.resiliency.aspect.AnnotationTimeoutAspectTest.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c)  2014 CrossBusiness, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.crossbusiness.resiliency.aspect;

import com.crossbusiness.resiliency.annotation.Async;
import com.crossbusiness.resiliency.annotation.Timeout;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

/**
 * Unit tests for {@link AnnotationTimeoutAspect}.
 *
 * Created by Sumanth Chinthagunta <xmlking@gmail.com> on 3/11/14.
 */
@RunWith(MockitoJUnitRunner.class)
public class AnnotationTimeoutAspectTest {
    static final Logger log = LoggerFactory.getLogger(AnnotationTimeoutAspectTest.class);

    @Mock
    Delegate delegateMock;

    @InjectMocks
    TestService testService;

    @Test
    public void method_that_takes_1000ms_and_annotated_with_timeout_of_2000ms_will_succeed()
            throws InterruptedException {
        doAnswer(new Answer<Object>() {
            public Object answer(InvocationOnMock invocation) throws InterruptedException {
                Object[] args = invocation.getArguments();
                TimeUnit.MILLISECONDS.sleep(1000);
                return args[0] + " back";
            }
        }).when(delegateMock).mockedMethod(anyString());

        String result = testService.timeout_2000ms("testArg");

        assertEquals("testArg back", result);
        verify(delegateMock).mockedMethod("testArg");
        verifyZeroInteractions(delegateMock);
    }

    @Test(expected = InterruptedException.class)
    public void method_that_takes_2000ms_and_annotated_with_timeout_of_1000ms_will_fail()
            throws InterruptedException {
        doAnswer(new Answer<Object>() {
            public Object answer(InvocationOnMock invocation) throws InterruptedException {
                TimeUnit.MILLISECONDS.sleep(2000);
                return "testArg back";
            }
        }).when(delegateMock).mockedMethod("testArg");

        String result = testService.timeout_1000ms("testArg");
        //Following lines will not be called as InterruptedException will be thrown.
        assertEquals(null, result);
        verify(delegateMock, timeout(2005)).mockedMethod("testArg");
        verifyZeroInteractions(delegateMock);
    }

    @Test
    public void void_method_that_takes_1s_and_annotated_with_timeout_of_2s_and_async_will_get_routed_asynchronously()
            throws InterruptedException {
        doNothing().when(delegateMock).mockedVoidMethod(anyString());
        testService.async_void_method_taking_1s_will_timeout_in_2s("testArg");

        verify(delegateMock, timeout(1100)).mockedVoidMethod("testArg");
        verifyZeroInteractions(delegateMock);
    }

    @Test
    public void void_method_that_takes_2s_and_annotated_with_timeout_of_1s_and_async_will_get_routed_asynchronously_but_timeout_before_calling_mockedVoidMethod()
            throws InterruptedException {
        doNothing().when(delegateMock).mockedVoidMethod(anyString());
        testService.async_void_method_taking_2s_will_timeout_in_1s("testArg");

        verify(delegateMock, never()).mockedVoidMethod("testArg");
        verifyZeroInteractions(delegateMock);
    }

    @Component
    private static class TestService {

        @Autowired
        private Delegate delegate;

        @Timeout(value = 2000, unit = TimeUnit.MILLISECONDS)
        public String timeout_2000ms(String arg) throws InterruptedException {
            return delegate.mockedMethod(arg);
        }

        @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
        public String timeout_1000ms(String arg) throws InterruptedException {
            return delegate.mockedMethod(arg);
        }

        /**
         * Note:  Precedence Order enforced. Timeout(outer), Async(inner){@link SystemArchitecture}.
         */
        @Timeout(value = 2, unit = TimeUnit.SECONDS)
        @Async
        public void async_void_method_taking_1s_will_timeout_in_2s(String arg) throws InterruptedException {
            log.debug(
                    "async_void_method_taking_1s_will_timeout_in_2s() get executed asynchronously, will run in defaultExecutor thread");
            TimeUnit.SECONDS.sleep(1);
            delegate.mockedVoidMethod(arg);
        }

        /**
         * Note:  Precedence Order enforced. Timeout(outer), Async(inner){@link SystemArchitecture}.
         */
        @Timeout(value = 1, unit = TimeUnit.SECONDS)
        @Async
        public void async_void_method_taking_2s_will_timeout_in_1s(String arg) throws InterruptedException {
            log.debug(
                    "async_void_method_taking_2s_will_timeout_in_1s() get executed asynchronously, will run in defaultExecutor thread");
            TimeUnit.SECONDS.sleep(2);
            delegate.mockedVoidMethod(arg);
        }

        /**
         * It should raise an error "Only methods that are declared with throws InterruptedException
         * may have an @Timeout annotation". This method must remain commented-out, otherwise there
         * will be a compile-time error. Uncomment to manually verify that the compiler produces an
         * error message due to the 'declare error' statement in
         * {@link AnnotationTimeoutAspect}.
         */
        //        @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
        //        public String timeout_compile_error(String arg) {
        //            return delegate.mockedMethod(arg);
        //        }

    }

    private static interface Delegate {
        String mockedMethod(String arg);

        void mockedVoidMethod(String arg);
    }
}