@Mocked太狠了,把类的所有的实例都Mock了。有时候我们希望一个类不同的实例有不同的Mock逻辑,怎么呢?

下面列举3种方法。还是以如何Mock类中的提到的AnOrdinaryClass为例。


//一个类多个实例的Mock 
public class OneClassManyInstanceMockingTest {
	// Mock方法一: 把实例传入Expectations的构造函数。适用场景: 只Mock实例的部分方法,对实例的类的其它实例不产生影响
	@Test
	public void testMocking1() {
		AnOrdinaryClass instance1 = new AnOrdinaryClass();
		AnOrdinaryClass instance2 = new AnOrdinaryClass();
		// 直接把实例传给Expectations的构造函数即可Mock这个实例
		new Expectations(instance1, instance2) {
			{
				instance1.ordinaryMethod();
				result = 20;
				instance2.ordinaryMethod();
				result = 200;
			}
		};
		AnOrdinaryClass instance3 = new AnOrdinaryClass();
		// instance1的ordinaryMethod被Mock了
		Assert.assertTrue(instance1.ordinaryMethod() == 20);
		// instance2的ordinaryMethod被Mock了
		Assert.assertTrue(instance2.ordinaryMethod() == 200);
		// instance3不受影响。
		Assert.assertTrue(instance3.ordinaryMethod() == 2);
	}
	// Mock方法二: 用@Mocked。适用场景: 类的所实例都需要Mock,但不同实例也能保留不同的Mock逻辑
	@Test
	public void testMocking2(@Mocked AnOrdinaryClass instance1, @Mocked AnOrdinaryClass instance2) {
		new Expectations() {
			{
				instance1.ordinaryMethod();
				result = 20;
				instance2.ordinaryMethod();
				result = 200;
			}
		};
		AnOrdinaryClass instance3 = new AnOrdinaryClass();
		// instance1的ordinaryMethod被Mock了
		Assert.assertTrue(instance1.ordinaryMethod() == 20);
		// instance2的ordinaryMethod被Mock了
		Assert.assertTrue(instance2.ordinaryMethod() == 200);
		// instance3受@Mock的影响。@Mock会把类的所有方法都Mock,返回类型为基本数据类型的返回0
		Assert.assertTrue(instance3.ordinaryMethod() == 0);
	}
	// Mock方法二: 用@Injectable。适用场景: 不是类的所实例都需要Mock,不同实例也能保留不同的Mock逻辑
	@Test
	public void testMocking3(@Injectable AnOrdinaryClass instance1, @Injectable AnOrdinaryClass instance2) {
		new Expectations() {
			{
				instance1.ordinaryMethod();
				result = 20;
				instance2.ordinaryMethod();
				result = 200;
			}
		};
		AnOrdinaryClass instance3 = new AnOrdinaryClass();
		// instance1的ordinaryMethod被Mock了
		Assert.assertTrue(instance1.ordinaryMethod() == 20);
		// instance2的ordinaryMethod被Mock了
		Assert.assertTrue(instance2.ordinaryMethod() == 200);
		// instance3不受@Injectable的影响。因为@Injectable只影响某个实例
		Assert.assertTrue(instance3.ordinaryMethod() == 2);
	}

}