JUNIT源码阅读-1

    一直听说junit的源码非常漂亮,里面用到了很多设计模式,也一直没有时间读,最近闲来无事,从今天开始阅读。

    我也不知道怎么有效的阅读源码,也没先去看看junit的架构,所以就将源码导入到eclipse中,从头开始一个一个类慢慢看。首先是一个annotation,这个不用说了吧。Assert类和Assume类。看了Assert类的代码,发现别人利用重载、泛型等技术使的代码的重用性非常高,举个例子看看:

/**
	 * Asserts that two byte arrays are equal. If they are not, an
	 * {@link AssertionError} is thrown with the given message.
	 * 
	 * @param message
	 *            the identifying message for the {@link AssertionError} (<code>null</code>
	 *            okay)
	 * @param expecteds
	 *            byte array with expected values.
	 * @param actuals
	 *            byte array with actual values
	 */
	public static void assertArrayEquals(String message, byte[] expecteds,
			byte[] actuals) throws ArrayComparisonFailure {
		internalArrayEquals(message, expecteds, actuals);
	}

	/**
	 * Asserts that two byte arrays are equal. If they are not, an
	 * {@link AssertionError} is thrown.
	 * 
	 * @param expecteds
	 *            byte array with expected values.
	 * @param actuals
	 *            byte array with actual values
	 */
	public static void assertArrayEquals(byte[] expecteds, byte[] actuals) {
		assertArrayEquals(null, expecteds, actuals);
	}

	/**
	 * Asserts that two char arrays are equal. If they are not, an
	 * {@link AssertionError} is thrown with the given message.
	 * 
	 * @param message
	 *            the identifying message for the {@link AssertionError} (<code>null</code>
	 *            okay)
	 * @param expecteds
	 *            char array with expected values.
	 * @param actuals
	 *            char array with actual values
	 */
	public static void assertArrayEquals(String message, char[] expecteds,
			char[] actuals) throws ArrayComparisonFailure {
		internalArrayEquals(message, expecteds, actuals);
	}

	/**
	 * Asserts that two char arrays are equal. If they are not, an
	 * {@link AssertionError} is thrown.
	 * 
	 * @param expecteds
	 *            char array with expected values.
	 * @param actuals
	 *            char array with actual values
	 */
	public static void assertArrayEquals(char[] expecteds, char[] actuals) {
		assertArrayEquals(null, expecteds, actuals);
	}

	/**
	 * Asserts that two short arrays are equal. If they are not, an
	 * {@link AssertionError} is thrown with the given message.
	 * 
	 * @param message
	 *            the identifying message for the {@link AssertionError} (<code>null</code>
	 *            okay)
	 * @param expecteds
	 *            short array with expected values.
	 * @param actuals
	 *            short array with actual values
	 */
	public static void assertArrayEquals(String message, short[] expecteds,
			short[] actuals) throws ArrayComparisonFailure {
		internalArrayEquals(message, expecteds, actuals);
	}

    可以看到,基本上都是调用了internalArrayEquals这个方法来实现的,这个方法接受了三个参数,而只有两个参数的判断数组相等,则使用了另外一个方法assertArrayEquals,我们来看看这个方法的实现:

	public static void assertArrayEquals(String message, char[] expecteds,
			char[] actuals) throws ArrayComparisonFailure {
		internalArrayEquals(message, expecteds, actuals);
	}

    可以看到里面同样是调用了internalArrayEquals方法,下面我们就来看看internalArrayEquals方法是怎么编写的:

	private static void internalArrayEquals(String message, Object expecteds,
			Object actuals) throws ArrayComparisonFailure {
		new ExactComparisonCriteria().arrayEquals(message, expecteds, actuals);
	}	

    其内部调用了一个比较器中的数组比较方法,慢慢来,我们马上就要看到是怎么比较两个数组的了,当然,如果是浮点型的数据的话,它还可以传入一个精度,我们这里就不考虑了哦。

	/**
	 * Asserts that two arrays are equal, according to the criteria defined by
	 * the concrete subclass. If they are not, an {@link AssertionError} is
	 * thrown with the given message. If <code>expecteds</code> and
	 * <code>actuals</code> are <code>null</code>, they are considered equal.
	 * 
	 * @param message
	 *            the identifying message for the {@link AssertionError} (
	 *            <code>null</code> okay)
	 * @param expecteds
	 *            Object array or array of arrays (multi-dimensional array) with
	 *            expected values.
	 * @param actuals
	 *            Object array or array of arrays (multi-dimensional array) with
	 *            actual values
	 */
	public void arrayEquals(String message, Object expecteds, Object actuals)
			throws ArrayComparisonFailure {
		if (expecteds == actuals)
			return;
		String header= message == null ? "" : message + ": ";

		int expectedsLength= assertArraysAreSameLength(expecteds,
				actuals, header);

		for (int i= 0; i < expectedsLength; i++) {
			Object expected= Array.get(expecteds, i);
			Object actual= Array.get(actuals, i);

			if (isArray(expected) && isArray(actual)) {
				try {
					arrayEquals(message, expected, actual);
				} catch (ArrayComparisonFailure e) {
					e.addDimension(i);
					throw e;
				}
			} else
				try {
					assertElementsEqual(expected, actual);
				} catch (AssertionError e) {
					throw new ArrayComparisonFailure(header, e, i);
				}
		}
	}

    这个里面可以支持多维数组的比较,所以有一个递归的过程,并且首先调用AssertArraySameLength方法检查了一下数组的长度是否相等:

	private int assertArraysAreSameLength(Object expecteds,
			Object actuals, String header) {
		if (expecteds == null)
			Assert.fail(header + "expected array was null");
		if (actuals == null)
			Assert.fail(header + "actual array was null");
		int actualsLength= Array.getLength(actuals);
		int expectedsLength= Array.getLength(expecteds);
		if (actualsLength != expectedsLength)
			Assert.fail(header + "array lengths differed, expected.length="
					+ expectedsLength + " actual.length=" + actualsLength);
		return expectedsLength;
	}

    然后判断数组中的元素是不是还是数组,所以需要检查一下:

	private boolean isArray(Object expected) {
		return expected != null && expected.getClass().isArray();
	}

    然后检查数组中的元素是否一一相等,使用到了

protected abstract void assertElementsEqual(Object expected, Object actual);

方法,可以看到这个方法是一个抽象方法,具体的实现是有子类来实现的,这种设计模式是将相同的部分抽象出来,不同的部分交给不同的子类来实现,其中spring中的jdbc封装类中都大量使用到了这种模式,这种模式叫做策略模式。

    然后Assert的一些其他的方式类似什么AssertNotNull,AssertNotEquals等等,就非常简单了,这里就不介绍了。

    Assume和其他的一些注解非常简单,这里就不一一演示了。

 

你可能感兴趣的:(源码,JUnit,架构)