PowerMock
You can mock constructors using PowerMock.
So in your case the test would look like something like this:
@RunWith(PowerMockRunner.class)
@PrepareForTest(MainActivityOfTheApp.class)
public class MainActivityOfTheAppTest{
private AsyncTaskFactory asyncTaskFactory;
private IntentFactory intentFactory;
private MainActivityOfTheApp mainActivityOfTheApp;
@Before
public void prepare() {
asyncTaskFactory = PowerMockito.mock(AsyncTaskFactory.class);
intentFactory = PowerMockito.mock(IntentFactory.class);
PowerMockito.whenNew(AsyncTaskFactory.class).withNoArguments().thenReturn(asyncTaskFactory);
PowerMockito.whenNew(IntentFactory.class).withNoArguments().thenReturn(intentFactory);
mainActivityOfTheApp = new MainActivityOfTheApp();
}
@Test
public void doTest() {
//mainActivityOfTheApp has the mocks in final field inside, no need for the setters.
}
}
I have to note, that PowerMock is powerful, but often has problems with complicated classloading (for example OSGI environments), or code coverage tools (jacoco for example). It works usually, but I have wasted some time with it.
Without PowerMock
Second possibility is to create package private(No modifier. Why not protected or public? See What's wrong with overridable method calls in constructors?) methods, which call the constructor like this:
public class MainActivityOfTheApp extends Activity {
private final IAsyncTaskFactory asyncTaskFactory = constructAsyncTaskFactory();
private final IIntentFactory intentFactory = constructIntentFactory();
IAsyncTaskFactory constructAsyncTaskFactory()
{
return new AsyncTaskFactory();
}
IIntentFactory constructIntentFactory()
{
return new IntentFactory();
}
...
}
Then in your unit test (the test must be in the same package as the tested class!) you override the construct*() methods:
public class MainActivityOfTheAppTest{
private AsyncTaskFactory asyncTaskFactory;
private IntentFactory intentFactory;
private MainActivityOfTheApp mainActivityOfTheApp;
@Before
public void prepare() {
asyncTaskFactory = mock(AsyncTaskFactory.class);
intentFactory = mock(IntentFactory.class);
mainActivityOfTheApp = new HackedMainActivityOfTheApp();
}
@Test
public void doTest() {
//mainActivityOfTheApp has the mocks in final field inside, no need for the setters.
}
private class HackedMainActivityOfTheApp extends MainActivityOfTheApp {
IAsyncTaskFactory constructAsyncTaskFactory()
{
return asyncTaskFactory;
}
IIntentFactory constructIntentFactory()
{
return intentFactory;
}
}
}
You can protect the construct* methods if you sign the jar containing the MainActivityOfTheApp. See https://stackoverflow.com/a/968612/337621 :
Also, patches are harder (you have to re-sign the jar), class-patches are impossible (all classes in a single package must have the same signature source) and splitting jars becomes a chore.