blob: 569a57f78480a0baee60fd3bee599b0cab344446 [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.testutil;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.After;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.Collection;
/**
* Test case with some support for automatically verifying mocks.
*
* This test case works transparently with EasyMock and PowerMock.
*/
public abstract class MockingTestCase extends TestCase {
private Collection<Object> mocks;
private Collection<IMocksControl> mockControls;
private boolean mocksReplayed;
private boolean usePowerMock;
/**
* Create and register a mock control.
*
* @return The mock control instance.
*/
protected final IMocksControl createMockControl() {
IMocksControl mockControl = EasyMock.createControl();
assertTrue("Adding mock control failed", mockControls.add(mockControl));
return mockControl;
}
/**
* Create and register a mock.
*
* Creates a mock and registers it in the list of created mocks, so it gets
* treated automatically upon {@code replay} and {@code verify};
* @param toMock The class to create a mock for.
* @return The mock instance.
*/
protected final <T> T createMock(Class<T> toMock) {
return createMock(toMock, null);
}
/**
* Create a mock for a mock control and register a mock.
*
* Creates a mock and registers it in the list of created mocks, so it gets
* treated automatically upon {@code replay} and {@code verify};
* @param toMock The class to create a mock for.
* @param control The mock control to create the mock on. If null, do not use
* a specific control.
* @return The mock instance.
*/
protected final <T> T createMock(Class<T> toMock, IMocksControl control) {
assertFalse("Mocks have already been set to replay", mocksReplayed);
final T mock;
if (control == null) {
if (usePowerMock) {
mock = PowerMock.createMock(toMock);
} else {
mock = EasyMock.createMock(toMock);
}
assertTrue("Adding " + toMock.getName() + " mock failed",
mocks.add(mock));
} else {
mock = control.createMock(toMock);
}
return mock;
}
/**
* Set all registered mocks to replay
*/
protected final void replayMocks() {
assertFalse("Mocks have already been set to replay", mocksReplayed);
if (usePowerMock) {
PowerMock.replayAll();
} else {
EasyMock.replay(mocks.toArray());
}
for (IMocksControl mockControl : mockControls) {
mockControl.replay();
}
mocksReplayed = true;
}
/**
* Verify all registered mocks
*
* This method is called automatically at the end of a test. Nevertheless,
* it is safe to also call it beforehand, if this better meets the
* verification part of a test.
*/
// As the PowerMock runner does not pass through runTest, we inject mock
// verification through @After
@After
public final void verifyMocks() {
if (!mocks.isEmpty() || !mockControls.isEmpty()) {
assertTrue("Created mocks have not been set to replay. Call replayMocks "
+ "within the test", mocksReplayed);
if (usePowerMock) {
PowerMock.verifyAll();
} else {
EasyMock.verify(mocks.toArray());
}
for (IMocksControl mockControl : mockControls) {
mockControl.verify();
}
}
}
@Override
public void setUp() throws Exception {
super.setUp();
usePowerMock = false;
RunWith runWith = this.getClass().getAnnotation(RunWith.class);
if (runWith != null) {
usePowerMock = PowerMockRunner.class.isAssignableFrom(runWith.value());
}
mocks = new ArrayList<>();
mockControls = new ArrayList<>();
mocksReplayed = false;
}
@Override
protected void runTest() throws Throwable {
super.runTest();
// Plain JUnit runner does not pick up @After, so we add it here
// explicitly. Note, that we cannot put this into tearDown, as failure
// to verify mocks would bail out and might leave open resources from
// subclasses open.
verifyMocks();
}
}