使用jmock测试System.in和System.out

阅读更多

本文要求读者已具备juit和jmock基础

在TDD过程中需要测试代码中的System.in和System.out。

技术难点包括

1、mock宿主还原

2、inout参数的行为模拟

3、mock system.in和out

1、测试主体

@Service
class ConsoleManagerBizImpl{
    private static Logger LOGGER = Logger
            .getLogger(ConsoleManagerBizImpl.class);

    public String readLine() {
        final Scanner scanner = new Scanner(System.in);
        String lineMessage = null;
        while (!StringUtils.hasText(lineMessage)) {
            lineMessage = scanner.nextLine();
        }
        return lineMessage;
    }


    public void writeLine(final String toWrite) {
        LOGGER.info(toWrite);
    }
}

 2、测试类

public class ConsoleManageBizImplTest {
	@Autowired
	private ConsoleManagerBizImpl biz;
	/**
	 * 既可 mock 接口也可以 mock 类
	 */
	protected final Mockery context = new JUnit4Mockery() {
		{
			setImposteriser(ClassImposteriser.INSTANCE);
		}
	};
        
         /**
	 * 改变预期的参数
	 * 
	 * @param result
	 *            预期结果
	 * @return 行为
	 */
	public Action ChangeBytes(final byte[] result) {
		return new ChangeBytesAction(result);
	}

	/**
	 * Test method for {@link ConsoleManagerBizImpl#readLine()}.
	 * 
	 * @throws IOException
	 *             异常
	 */
	@Test
	public void testReadLine() throws IOException {
		final InputStream origin = System.in;
		final InputStream mockStream = context.mock(InputStream.class);
		System.setIn(mockStream);

		context.checking(new Expectations() {
			{
				final byte[] b = new byte[8192];
				oneOf(mockStream).read(b, 0, 8192);

				final byte[] result = new byte[8192];
				result[0] = '1';
				result[1] = '1';
				result[2] = '\n';
				will(ChangeBytes(result));
			}
		});

		Assert.assertEquals("11", biz.readLine());

		System.setIn(origin);
	}

	/**
	 * Test method for {@link ConsoleManagerBizImpl#writeLine(String)}
	 */
	@Test
	public void testWriteLine() {
		final String toWrite = "109-230-912-0";
		biz.writeLine(toWrite);
	}
}

 

 3、mockaction

class ChangeBytesAction implements Action {
	private final byte[] result;

	/**
	 * @param result
	 *            结果
	 */
	public ChangeBytesAction(final byte[] result) {
		this.result = result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
	 */
	public void describeTo(final Description description) {
		description.appendText("change ").appendValueList("", ", ", "", result)
				.appendText(" value");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jmock.api.Invokable#invoke(org.jmock.api.Invocation)
	 */
	public Object invoke(final Invocation invocation) throws Throwable {
		final byte[] bytesArray = (byte[]) invocation.getParametersAsArray()[0];
		for (int i = 0; i < result.length; i++) {
			bytesArray[i] = result[i];
		}
		return result.length;
	}
}

 4、如果在测试主体中使用System.out输出,则下面的代码可以对其进行测试

 /**
     * Test method for {@link ConsoleManagerBizImpl#writeLine(String)}
     */
     @Test
     public void testWriteLine() {
          final PrintStream origin = System.out;
          final PrintStream mockout = context.mock(PrintStream.class);
          System.setOut(mockout);

          final String toWrite = "109-230-912-0";
          context.checking(new Expectations() {
               {
                    oneOf(mockout).println(toWrite);
               }
          });
          biz.writeLine(toWrite);

          System.setOut(origin);
     }
}

你可能感兴趣的:(jmock,junit,system.in,system.out,TDD)