public Object answer(InvocationOnMock invocation) { if (methodsGuru.isToString(invocation.getMethod())) { Object mock = invocation.getMock(); MockName name = mockUtil.getMockName(mock); if (name.isDefault()) { return "Mock for " + mockUtil.getMockSettings(mock).getTypeToMock().getSimpleName() + ", hashCode: " + mock.hashCode(); } else { return name.toString(); } } else if (methodsGuru.isCompareToMethod(invocation.getMethod())) { //see issue 184. //mocks by default should return 0 if references are the same, otherwise some other value because they are not the same. Hence we return 1 (anything but 0 is good). //Only for compareTo() method by the Comparable interface return invocation.getMock() == invocation.getArguments()[0] ? 0 : 1; } Class<?> returnType = invocation.getMethod().getReturnType(); return returnValueFor(returnType); }
public void maybeRedefineMockName(Object mock, String newName) { MockName mockName = getMockName(mock); //TODO SF hacky... if (mockName.isDefault() && getMockHandler(mock).getMockSettings() instanceof CreationSettings) { ((CreationSettings) getMockHandler(mock).getMockSettings()).setMockName(new MockNameImpl(newName)); } }
private Map<String, Object> getMocksWithNames() { Map<String, Object> result = new HashMap<String, Object>(); MockUtil mockUtil = new MockUtil(); for (Object mock : getMocks()) { MockName mockName = mockUtil.getMockName(mock); result.put(mockName.toString(), mock); } return result; }
public MockName getMockName() { return mockName; }
public CreationSettings<T> setMockName(MockName mockName) { this.mockName = mockName; return this; }
public MockName getMockName(Object mock) { return getMockHandler(mock).getMockSettings().getMockName(); }
/** * Custom implementation of the <code>writeReplace</code> method for serialization. * <p/> * Here's how it's working and why : * <ol> * <li> * <p>When first entering in this method, it's because some is serializing the mock, with some code like : * <pre class="code"><code class="java"> * objectOutputStream.writeObject(mock); * </code></pre> * So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and * execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock. * At this point, the code will return an * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy}.</p> * </li> * <li> * <p>Now, in the constructor * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy#AcrossJVMMockSerializationProxy(Object)} * the mock is being serialized in a custom way (using * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream}) to a * byte array. So basically it means the code is performing double nested serialization of the passed * <code>mockitoMock</code>.</p> * * <p>However the <code>ObjectOutputStream</code> will still detect the custom * <code>writeReplace</code> and execute it. * <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)} * doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the * written stream, <strong><code>writeReplace</code> is always called by * <code>ObjectOutputStream</code></strong>.)</em></p> * * <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using * a flag that marks the mock as already being replaced, and then shouldn't replace itself again. * <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs * to be protected against concurrent access, hence the reentrant lock.</p> * </li> * </ol> * * @param mockitoMock The Mockito mock to be serialized. * @return A wrapper ({@link AcrossJVMMockSerializationProxy}) to be serialized by the calling ObjectOutputStream. * @throws ObjectStreamException */ public Object writeReplace(Object mockitoMock) throws ObjectStreamException { try { // reentrant lock for critical section. could it be improved ? mutex.lock(); // mark started flag // per thread, not per instance // temporary loosy hack to avoid stackoverflow if (mockIsCurrentlyBeingReplaced()) { return mockitoMock; } mockReplacementStarted(); return new AcrossJVMMockSerializationProxy(mockitoMock); } catch (IOException ioe) { MockUtil mockUtil = new MockUtil(); MockName mockName = mockUtil.getMockName(mockitoMock); String mockedType = mockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName(); throw new MockitoSerializationIssue(join( "The mock '" + mockName + "' of type '" + mockedType + "'", "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :", " " + ioe.getMessage() ), ioe); } finally { // unmark mockReplacementCompleted(); mutex.unlock(); } }
/** * Custom implementation of the <code>writeReplace</code> method for serialization. * * Here's how it's working and why : * <ol> * <li> * <p>When first entering in this method, it's because some is serializing the mock, with some code like : * <pre class="code"><code class="java"> * objectOutputStream.writeObject(mock); * </code></pre> * So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and * execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock. * At this point, the code will return an {@link AcrossJVMMockSerializationProxy}.</p> * </li> * <li> * <p>Now, in the constructor {@link AcrossJVMMockSerializationProxy#AcrossJVMMockSerializationProxy(Object)} * the mock is being serialized in a custom way (using {@link MockitoMockObjectOutputStream}) to a * byte array. So basically it means the code is performing double nested serialization of the passed * <code>mockitoMock</code>.</p> * * <p>However the <code>ObjectOutputStream</code> will still detect the custom * <code>writeReplace</code> and execute it. * <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)} * doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the * written stream, <strong><code>writeReplace</code> is always called by * <code>ObjectOutputStream</code></strong>.)</em></p> * * <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using * a flag that marks the mock as already being replaced, and then shouldn't replace itself again. * <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs * to be protected against concurrent access, hence the reentrant lock.</p> * </li> * </ol> * * * @param mockitoMock The Mockito mock to be serialized. * @return A wrapper ({@link AcrossJVMMockSerializationProxy}) to be serialized by the calling ObjectOutputStream. * @throws ObjectStreamException */ public Object writeReplace(Object mockitoMock) throws ObjectStreamException { try { // reentrant lock for critical section. could it be improved ? mutex.lock(); // mark started flag // per thread, not per instance // temporary loosy hack to avoid stackoverflow if(mockIsCurrentlyBeingReplaced()) { return mockitoMock; } mockReplacementStarted(); return new AcrossJVMMockSerializationProxy(mockitoMock); } catch (IOException ioe) { MockUtil mockUtil = new MockUtil(); MockName mockName = mockUtil.getMockName(mockitoMock); String mockedType = mockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName(); throw new MockitoSerializationIssue(join( "The mock '" + mockName + "' of type '" + mockedType + "'", "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :", " " + ioe.getMessage() ), ioe); } finally { // unmark mockReplacementCompleted(); mutex.unlock(); } }