Mock Constructor

Mock System.exit中,我們有遇到exception path該如何測的問題。第一個方法是將new Example抽出為static的createExample,再用powermock去mock它 (記得在efficiency java中看過,它建議你將new Example寫成createExample的method去產生instance);第二個方法是直接使用powermock的mock construcor功能。無論如何,在mock出example instance後,都需要再mock doSomething讓它拋出exception。在這我使用第二個方法為大家做說明。

package org.tonylin.powermock;
 
public class Example {
 
	public Example(){
 
	}
 
	public void doSomething(){
 
	}
 
	public static void main(String[] args) {
		try {
			new Example().doSomething();
		} catch( Exception e ){
			System.exit(1);
		} finally {
			System.exit(0);
		}
	}
 
}

首先我們需mock System.exit為1的情況,接著透過PowerMock.createMockAndExpectNew(Example.class)讓new Example都會產生這個mock object。在example.doSomething()後,透過PowerMock.expectLastCall().andStubThrow去拋出RuntimeException,這能夠讓main程式出現exception情況。最後reply再執行。

@RunWith(PowerMockRunner.class)
@PrepareForTest({Example.class})
public class TestExample {
	@Test
	public void testMainWithException() throws Exception{
		// mock System.exit
		PowerMock.mockStatic(System.class);
		System.exit(1);
		PowerMock.expectLastCall().times(1);
 
		// mock constructor
		Example example = PowerMock.createMockAndExpectNew(Example.class);
		example.doSomething();
		PowerMock.expectLastCall().andStubThrow(new RuntimeException());
 
		PowerMock.replayAll();
 
		Example.main(new String[0]);
	}
}

如果你使用的情況是Class A去new Class B,而你要mock Class B,要記得把Class A加到PrepareForTest中喔!

PowerMock.createMockAndExpectNew(Example.class)的寫法,也可改為這種寫法:

	Example example = PowerMock.createNiceMock(Example.class);
	PowerMock.expectNew(Example.class).andReturn(example);
但我想沒人會想做多寫一行的事情吧? (一行也是生產力嗎?)