Code Monkey home page Code Monkey logo

easymock's Introduction

EasyMock

Join the chat at https://gitter.im/easymock/easymock

Download latest version

EasyMock is a Java library that provides an easy way to use Mock Objects in unit testing.

You can find the website and user documentation at http://easymock.org.

Developer information

Build status

Build Status Maven Central

Environment setup

I'm using:

  • IntelliJ 2023.2.1 Ultimate (thanks to JetBrains for the license)
  • Maven 3.9.2

You can also use Eclipse. I tried

  • Eclipse 2020.12 (but there was a weird compilation issue with ASM)

To configure your local workspace:

  • Import the Maven parent project to Eclipse or IntelliJ
  • Import the Eclipse formatting file EasyMock-formatter.xml (usable in Eclipse or IntelliJ)

To build EasyMock with Maven

There are three different levels of build.

Build without any active profile

It is a basic compilation of the application.

mvn install

Full build

This build will check code coverage using Jacoco, run spotbugs and validate that the license headers are correctly set.

mvn install -PfullBuild

Deploy build

This is the build to launch to deploy to the surefire repository. It assembles the application and add the gpg checksum. You will usually launch it on top of the full build.

The command line will ask you to give the passphrase for the gpg private key.

mvn install -PdeployBuild

To compile EasyMock in Eclipse

  • Install m2e
  • Import the EasyMock Maven parent project to your Eclipse workspace

To compile EasyMock in IntelliJ

  • Import the EasyMock Maven parent project as a New IntelliJ project

To update the versions

  • mvn versions:set -DnewVersion=X.Y -Pall
  • mvn versions:commit -Pall if everything is ok, mvn versions:revert -Pall otherwise

Configure to deploy to Maven Central repository

  • You will first need to add something like this to your settings.xml
<servers>
    <server>
        <id>ossrh</id>
        <username>sonatypeuser</username>
        <password>sonatypepassword</password>
    </server>
</servers>
  • Then follow the instructions from the site below to create your key to sign the deployed items

To build the maven site (with spotbugs, checkstyle, jdepends and JavaNCSS reports)

  • You will to give enough memory to maven with export MAVEN_OPTS=-Xmx512m (or setting it as environment variable)
  • Then type mvn site

To check dependencies and plugins versions

mvn versions:display-dependency-updates versions:display-plugin-updates -Pall

To download the sources associated to our dependencies

mvn dependency:resolve -Dclassifier=sources

To update the license

mvn validate license:format -Pall

To upgrade the Maven wrapper

mvn wrapper:wrapper

To run Sonar

mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent test sonar:sonar

Android

  • Install the Android SDK
  • Configure a device (real or simulated)
  • Add an ANDROID_HOME to target the Android SDK
  • Possibly put these in your path: $ANDROID_HOME/platform-tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/emulator
  • To launch an emulator from command line
    • To list the configured device: emulator -list-avds
    • To launch: emulator -avd Nexus_5X_API_28
  • Activate the debug mode if it's a real device
  • mvn install -Pandroid

To bundle EasyMock and deploy

  • Make sure the poms are on the snapshot of the version you want to deploy
  • Make sure jq is installed. If not, install it with your favorite package manager (brew install jq, choco install jq, apt-get install jq, yum install jq, etc.).
  • Add a little speech on the features in "ReleaseNotes.md" (remove the Change Log part, which will be regenerated automatically)
  • Set the gpg_passphrase as environment variables
  • Launch ./deploy-easymock.sh (major|minor|patch) where the parameter tells which version number should be incremented at the end
  • During the deployment, you will be asked to do different things. Do them
  • Announce to gitter, tweet and blog ;-)

In case of a failure during the build before the deployment, do mvn versions:commit -Pall and start over.

If something was staged in Maven Central, you can drop the staging repository with mvn nexus-staging:drop.

Deploy the website

  • In local:
    • Go to the EasyMock root directory
    • Make sure the website directory is clean
    • ./deploy-website.sh

Start next version

In local:

mvn versions:set -DnewVersion=X.Z-SNAPSHOT -Pall
mvn versions:commit -Pall

easymock's People

Contributors

agilespirit avatar based2 avatar danners avatar dependabot[bot] avatar earthcitizen avatar ffang avatar gitter-badger avatar grimreaper avatar henri-tremblay avatar ijuma avatar jlleitschuh avatar john9x avatar jonyd avatar juherr avatar jungster124 avatar prakgoya avatar reftel avatar tammofreese avatar tiwanari avatar toby-murray-snow-software avatar todderz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easymock's Issues

Problems with ParameterMatcher.parameterMatches()

Migrated from: CodeHaus issue EASYMOCK-3
Original reporter: Henri Tremblay


We have found some strange behavior when using a
custom ParameterMatcher's parameterMatches()
method.

I have attached a zip file of a project that illustrates the
problems (it is an Eclipse project). By looking at the
test design and console output, the bugs should be
apparent.

Here is a summary and explanation of the bugs. The
example test uses a ClassUnderTest which calls a void
method on a Collaborator class, passing a single
parameter.

  1. The parameterMatches method is invoked too many
    times. Specifically, it seems to be invoked once for the
    first call, twice for the second call, and twice for the
    third call - even though there is only one parameter for
    the method being called.
  2. The expected value passed is not correct (this is
    probably related to the previous bug). The first
    expected value continues to be passed.

Regression caused by new threadsafe API and defaults

Migrated from: CodeHaus issue EASYMOCK-16
Original reporter: Henri Tremblay


EasyMock 2.4 introduced a new threadsafe mode, but kept mocks non-threadsafe by default for performance reasons and due to "unknown side effects" [1].

The problem is that non-threadsafe mocks which are used by multiple threads now cause exceptions to be thrown, whereas in 2.3 and earlier there was no exception thrown. This change in default behavior will especially affect testing of Swing apps, which often need to deal with multiple threads (EDT, etc).

As things stand, the cost of upgrading to EasyMock 2.4 and going through all of our tests and changing the code to make all mocks threadsafe is prohibitive.

The possible fixes (as I see them) are:

  1. Change the behavior of MocksBehavior#checkCurrentThreadSameAsLastThread() so that it just logs a warning, rather than throwing an exception.
  2. Remove MocksBehavior#checkCurrentThreadSameAsLastThread(), so that non-threadsafe use matches version 2.3 and prior (no exception is thrown).
  3. Make all mocks threadsafe by default.
  4. Provide an easy way to set the default threadsafe value globally, rather than having to do it mock-by-mock or MocksControl-by-MocksControl.

Personally I think #3 is the best option, especially with the new JVMs that don't incur the synchronization cost unless necessary [2], but if that's completely out of the question, my order of preference after #3 would be #2, #1 and finally #4 (which would just barely be acceptable).

Looking forward to feedback,

Daniel

[1] http://tech.groups.yahoo.com/group/easymock/message/1205

[2] http://java.sun.com/performance/reference/whitepapers/6_performance.html#2.1

CodeGenerationException

Migrated from: CodeHaus issue EASYMOCK-22
Original reporter: Henri Tremblay


When mocking classes that are signed as part of a web start deployment, I am getting the below exception. The same bug was reported against Mockito. That project fixed the problem by upgrading to cglib 2.2. (http://code.google.com/p/mockito/issues/detail?id=11)

net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
at org.easymock.classextension.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:107)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:40)
at org.easymock.classextension.EasyMock.createMock(EasyMock.java:46)
at com.monsanto.tps.capacitymanager.builder.ICBRowRequestBuilder_UT.getRowBeans_doesstuff_itshould(ICBRowRequestBuilder_UT.java:131)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
... 28 more
Caused by: java.lang.SecurityException: class "my.class$$EnhancerByCGLIB$$5644046a"'s signer information does not match signer information of other classes in the same package
at java.lang.ClassLoader.checkCerts(Unknown Source)
at java.lang.ClassLoader.preDefineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
... 33 more

Update maven-javadoc-plugin to 2.7 (Maven build broken)

Migrated from: CodeHaus issue EASYMOCK-43
Original reporter: Henri Tremblay


The existing version (2.6.1) of maven-javadoc-plugin used in the build can cause a top-level build to fail on Maven 2.2.1:

[INFO] Unable to find resource 'org.easymock:easymock:jar:3.1-SNAPSHOT' in repository snapshots (http://snapshots)
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Failed to resolve artifact.

Missing:
----------
1) org.easymock:easymock:jar:3.1-SNAPSHOT

I believe that this is a known problem with this plugin, which can be fixed by moving up to version 2.7.

POM patch attached.

MockBuilder.addMockedMethod should fail for final methods

Migrated from: CodeHaus issue EASYMOCK-44
Original reporter: Henri Tremblay


MockBuilder.addMockedMethod should throw an IllegalArgumentException if the method is final. Currently, the method call seems to succeed, but the method is not mocked, leading to unexpected behaviour (I just fell in this trap). Since as documented mocking of final methods is not supported, trying to mock a final method should fail fast.

expected method not called in overloaded generic methods

Migrated from: CodeHaus issue EASYMOCK-34
Original reporter: Henri Tremblay


Suppose we have:

public interface A<T, U>
{
public U foo(T t);
}

public interface B extends A<TImpl, UImpl>
{
public UImpl foo(TImpl t);
}

Granted, the fact that B even defines this method is totally useless, but it is syntactically valid, and is seen from time to time after partial refactorings when someone misses a method.

Now in a TestCase we have:

B b = createMock(B.class);
expect(foo(isA(TImpl.class)));
replay(b);

b.foo(new TImpl());

This causes an assertion failure on an unexpected method call to foo.

However,

A<TImpl, UImpl> b = createMock(A.class);
expect(foo(isA(TImpl.class)));
replay(b);

b.foo(new TImpl());

succeeds!

Actual value in byte array failure is not helpful

Migrated from: CodeHaus issue EASYMOCK-18
Original reporter: Henri Tremblay


When using EasyMock.aryEq("TestValue2".getBytes()) the value that was passed in did not match and the Actual that is printed out is the byte array reference. I would expect that the actual be printed out in the same format that the expected is printed out in a list format.

Example:
java.lang.AssertionError:
Unexpected method call create2([B@117a8bd):
create2([84, 101, 115, 116, 86, 97, 108, 117, 101, 50]): expected: 1, actual: 0

Can't replay a mock on interface without cglib

Migrated from: CodeHaus issue EASYMOCK-40
Original reporter: Henri Tremblay


If cglib isn't in the classpath, calling EasyMock.replay/reset/verify of a mock will throw a NoClassDefFoundError.

However, it does work using EasyMockSupport or through a mock control.

Concurrency issue in UnorderedBehavior

Migrated from: CodeHaus issue EASYMOCK-5
Original reporter: Henri Tremblay


Submitted by Serguei Khramtchenko

I got the exception below when using easymock in a thread pool and looked at the source code inside UnorderedBehavior, addExpected method. The array list is not concurrent.

Exception in thread "pool-1-thread-1"
java.util.ConcurrentModificationException
at
java.util.AbstractList$Itr.checkForComodification(AbstractList.java:
449)
at java.util.AbstractList$Itr.next(AbstractList.java:420)
at
org.easymock.internal.UnorderedBehavior.addExpected
(UnorderedBehavior.java:22)
at
org.easymock.internal.MocksBehavior.addExpected(MocksBehavior.java:41)
at
org.easymock.internal.RecordState.times(RecordState.java:185)
at
org.easymock.internal.RecordState.closeMethod(RecordState.java:229)
at
org.easymock.internal.RecordState.invoke(RecordState.java:62)
at
org.easymock.internal.MockInvocationHandler.invoke
(MockInvocationHandler.java:24)
at
org.easymock.internal.ObjectMethodsFilter.invoke
(ObjectMethodsFilter.java:56)
at $Proxy7.log(Unknown Source)
at
com.casenet.core.executor.ThreadPool.beforeExecute(ThreadPool.java:62)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask
(ThreadPoolExecutor.java:648)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)

finalize() should be treated specially

Migrated from: CodeHaus issue EASYMOCK-21
Original reporter: Henri Tremblay


If I lose all references to a mock in a test, it may (or may not) get GCed before the test is over. If it does happen, this creates an expectation of a call to finalize(), making the test fail. Since the GC is unpredictable, this leads to flaky tests.
We should treat finalize() specially, probably by ignoring it completely, since it makes no sense to expect it given that there's no way to force GC.

IllegalStateException: incompatible return value type

Migrated from: CodeHaus issue EASYMOCK-36
Original reporter: Henri Tremblay


The following code leads to an "java.lang.IllegalStateException: incompatible return value type"
in the second expect call.

public static class MockTestGetLong {

public Long getLong() {
  return 1l;
}

}

public void testEasyMock() {
MockTestGetLong mock1 = createMock(MockTestGetLong.class);
expect(mock1.getLong()).andReturn(2l);
expect(mock1.toString()).andReturn("foo");
}

The cause is that the first call (getLong()) sets the return type of the state object for the last call to Long. But the second call (toString()) does not set the return type of the state object thus causing the second call to andReturn fails to fail since it expects a Long but gets a String.

Base methods aren't called from a constructor

Migrated from: CodeHaus issue EASYMOCK-35
Original reporter: Henri Tremblay


Partially mocked classes that use a constructor are affected when constructor calls a non-mocked method. In this case the call is intercepted by EasyMock and forwarded to the proxy, while it should have gone to the base method.
It happens because at the time constructor is called in ClassProxyFactory.createProxy() the MockMethodInterceptor instance doesn't have mockedMethods set. To fix this I'd suggest to use the same hack as used for ConstructorArgs - adding a ThreadLocal variable to ClassExtensionHelper.
Please see attached the proposed fix.

Please note: the same bug migrated to EasyMock 3.0 codebase

NPE with varargs in record state

Migrated from: CodeHaus issue EASYMOCK-11
Original reporter: Henri Tremblay


When recording a varargs method together with matchers like isA() a NullPointException occurs.

See the attached test case that reveals the issue.

Possible bug with captures()

Migrated from: CodeHaus issue EASYMOCK-19
Original reporter: Henri Tremblay


I think I may have run into a possible bug with using captures() to capture a parameter passed to a mocked method.

I've attached a (very simplified) test case to prove the behavior.

Please note that this is just a simplified test case - I know that I could specify the exact value of the arguments I expect passed to my mock, but in my real code the arguments are complex objects with a number of fields, and in the unit test (of the class using the mocked component), I want to capture the object so I can assert against just a few of those fields without re-creating the entire object in my test case.

Can someone please confirm if this is indeed a bug or if I am simply using this method wrong?

Thanks
Matt Brown
[email protected]

Bridge methods are always mocked, regardless of partial mock

Migrated from: CodeHaus issue EASYMOCK-39
Original reporter: Henri Tremblay


EasyMock bridge method handling is wrong. It always forwards the invocation against a bridge method to the mock interceptor. For partial mocks, this is undesirable.

The following test case reproduces the bug (also included in the patch):

static abstract class GenericHolder<T> {
    abstract void set(T value);

    final void go(final T value) {
        set(value);
    }
}

static class StringHolder extends GenericHolder<String> {
    String value;

    @Override
    void set(final String value) {
        this.value = value;
    }
}

@Test
public void testBridgeMethod() {
    final StringHolder holder = EasyMock.createMock(StringHolder.class, new Method[0]);
    holder.go("hello");
    Assert.assertEquals("hello", holder.value);
}

Cglib's CallbackFilter can already filter out all bridge methods so that they follow the original dispatching.
Attached patch (against the svn trunk) removes BridgeMethodResolver and uses cglib's CallbackFilter to handle bridge methods properly.

Provide mockType to createMock() method

Migrated from: CodeHaus issue EASYMOCK-24
Original reporter: Henri Tremblay


Purpose is to be able to "dynamically" create nice/strict/normal mocks without having to call the "appropriate" method.

Workaround is to directly use MockControl instead of EasyMock entry point :
IMocksControl ctrl = new MocksControl(MocksControl.MockType.STRICT);
MyMock mock = ctrl.createMock(MyMock.class);

This is only a "cosmetic" feature ... no real need to really implement this fastly.

Non-uniform footer on the website

Migrated from: CodeHaus issue EASYMOCK-32
Original reporter: Henri Tremblay


The different pages of the web site have slightly different footers. Sometimes Henri is mentioned, sometimes not. There's a link to Henri's old blog.

The attached patch provides the same footer to every page.

Exception message improvements

Migrated from: CodeHaus issue EASYMOCK-29
Original reporter: Henri Tremblay


Take this code:

public class EasyMockMessages {

interface ISomething {
    public int someOperation(String s);
}

@Test
public void someTest() throws Exception {
    ISomething something = EasyMock.createMock(ISomething.class);
    EasyMock.expect(something.someOperation("hello")).andReturn(42);
    EasyMock.replay(something);

    something.someOperation("hello\t");

}

}

This gives the following error now

java.lang.AssertionError:
Unexpected method call someOperation("hello "):
someOperation("hello"): expected: 1, actual: 0

This error could be more helpful by:

  • Using a ComparisonFailure exception which would allow to compare the actual and expected method in a Result Comparison Diff in Eclipse IDE (ComparisonFailure still allows a custom plain text message, fake screenshot attached)
  • Having the text "Expected method call" in front of the 3rd line (I think this would clarify the message)
  • Quoting special characters as "\t", "\n" to make tiny but important differences regarding "invisible" characters visible

User guide refers to methods not in latest release

The user guide refers to methods which are on the master branch but not in the latest release (3.3.1), for example EasyMock.mock() and EasyMock.strictMock().

I think this can be confusing especially for new users. Recently saw a Stack Overflow question about this.

EasyMock should behave normally after a failure

Migrated from: CodeHaus issue EASYMOCK-6
Original reporter: Henri Tremblay


Submitted by Mike Dunbar

Running the main method of this class demonstrates the issue.


public class DemoEasyMockIssue {
public static interface TheInterface {
public String foo();
public String bar();
}

public static void main(String[] args) {
TheInterface mock =
createMock(TheInterface.class);
expect(mock.foo()).andReturn("foo").anyTimes();
replay(mock);
mock.foo();
System.out.println("Calling foo works as "+
"anticipated, before the call to bar.");

  try {
     mock.bar();
  }
  catch(AssertionError error) {
     System.out.println("Calling bar gives the " + 
        "anticipated error: " + error);
  }

  try {
     mock.foo();
  }
  catch(AssertionError error) {
     System.out.println("Calling foo again after" +   
        "bar gives an unanticipated error: " +  
        error);
  }

}

}

To me it seems like a bug that mocks report expected calls as unexpected, after any call to an unexpected method. At the very least, the error message is misleading because it only says that the expected
method call was unexpected. I'm sure it's probably the case that you would normally be calling the unexpected method as part of a test, fail before you ever try and make a subsequent call on the expected method, and this wouldn't matter. But due to one of the automated testing tools that we use this isn't desirable. I would like subsequent calls to expected methods to behave based on the recording.

Is this reasonable?

Stack trace clobbered when exception thrown by IAnswer impl

Migrated from: CodeHaus issue EASYMOCK-23
Original reporter: Henri Tremblay


I've implemented a custom IAnswer handler and set up my mock to return the the result computed by the IAnswer impl. Unfortunately, my IAnswer implementation had a bug in it, resulting in a NullPointerException being thrown. Problem is that it looks like MockInvocationHandler:34 (in v2.4) is replacing the stack trace of my NullPointerException with the stack trace generated at MockInvocationHandler:34. Here's the EasyMock code I'm referring to:

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    try {
        if (control.getState() instanceof RecordState) {
            LastControl.reportLastControl(control);
        }
        return control.getState().invoke(
                new Invocation(proxy, method, args));
    } catch (RuntimeExceptionWrapper e) {
        throw e.getRuntimeException().fillInStackTrace();
    } catch (AssertionErrorWrapper e) {
        throw e.getAssertionError().fillInStackTrace();
    } catch (ThrowableWrapper t) {
        throw t.getThrowable().fillInStackTrace();
    }
}

Here's my the stack trace from my test failure:

[junit] java.lang.NullPointerException
[junit]     at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:34)
[junit]     at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:61)
[junit]     at $Proxy6.getEmailInfos(Unknown Source)
[junit]     at com.linkedin.invitations.internal.impl.InvitationServiceImpl.getRecipientKeys(InvitationServiceImpl.java:297)
// snip: test code
[junit]     at test.fwk.util.core.BaseTestSuiteCore.run(BaseTestSuiteCore.java:139)

The reported NPE actually occurred further downstream in my IAnswer implementation. However, the resulting stack trace has erased those frames. I'd like the stack trace to look like this :)

[junit] java.lang.NullPointerException
[junit]     at com.linkedin.invitations.internal.impl.EOSAnswerFactory$1.answer(EOSAnswerFactory.java:91)
[junit]     at com.linkedin.invitations.internal.impl.EOSAnswerFactory$1.answer(EOSAnswerFactory.java:83)
[junit]     at org.easymock.internal.Result.answer(Result.java:60)
[junit]     at org.easymock.internal.ReplayState.invokeInner(ReplayState.java:41)
[junit]     at org.easymock.internal.ReplayState.invoke(ReplayState.java:33)
[junit]     at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:27)
[junit]     at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:61)
[junit]     at $Proxy6.getEmailInfos(Unknown Source)
[junit]     at com.linkedin.invitations.internal.impl.InvitationServiceImpl.getRecipientKeys(InvitationServiceImpl.java:297)

Perhaps I'm misunderstanding how fillInStackTrace() works, but it does appear to replace the existing stack trace. fillInStackTrace() is a native call, so perhaps my JVM (Mac) is screwing things up.

In any case, this clobbering of the stack trace is inconvenient in this scenario, as it looks like EasyMock internals are breaking, when it was really my own code. A debugger helped settle the matter, but it would have been faster to just see my code show up in the original stack trace. Is ther

Here's a similar, but seemingly unrelated bug I came across. It looks like it's a more general case of what I'm experiencing. Thanks for your help on this!

http://sourceforge.net/tracker/?func=detail&aid=824925&group_id=82958&atid=567837

Mock assertion counting does not seem to be thread safe

Migrated from: CodeHaus issue EASYMOCK-7
Original reporter: Henri Tremblay


Hi,
I had a test in which a single mock object was called back by various different threads concurrently and it randomly failed to count the calls to each method, leading to unexpected test failures.

I then modified the test so that each thread had its own mock object to hit and I got back repeatable successes.
The drawback is, my test got quite a bit more complex.

Would it be possible to make mock objects thread safe, or to have the ability to create a synchronized wrapper for them, something like EasyMock.synchronizedMock(mock), mimicking what Collections.synchronizedXXX(collection) methods do?

Reset does not seem to be working.

Migrated from: CodeHaus issue EASYMOCK-2
Original reporter: Nate Corlet


@test
@ExpectedException (SupportDatabaseException.class)
public void testGetConsultantsByUnitExceptions() throws Exception {
JdbcTemplate realTemplate = target.getJdbcTemplate();
JdbcTemplate jdbcTemplateMock = createMock("database", JdbcTemplate.class);
try {
System.err.println("a");
List consultants = new ArrayList();
System.err.println("b");
expect(jdbcTemplateMock.query((String)anyObject(), (Object[])anyObject(),
(int[])anyObject(), (RowMapper)anyObject())).andThrow(new EmptyResultDataAccessException(2));
System.err.println("c");
replay(jdbcTemplateMock);
System.err.println("d");
target.setJdbcTemplate(jdbcTemplateMock);
System.err.println("e");
consultants = target.getByUnitId("363774");
System.err.println("f");
assertThat(consultants, equalTo(isNull()));
System.err.println("g");
verify(jdbcTemplateMock);
System.err.println("h");
reset(jdbcTemplateMock);
System.err.println("i");
expect(jdbcTemplateMock.query((String)anyObject(), (Object[])anyObject(),
(int[])anyObject(), (RowMapper)anyObject())).andThrow(new IllegalArgumentException("testGetConsultantsByUnitExceptions Fail. This is expected."));
System.err.println("j");
replay(jdbcTemplateMock);
System.err.println("k");
target.getByUnitId("363774");
System.err.println("l");
} finally {
System.err.println("m");
System.err.println("n");
verify(jdbcTemplateMock);
System.err.println("o");
target.setJdbcTemplate(realTemplate);
System.err.println("p");
}
}

The output from the above is:
a
b
c
d
e
f
g
h
i
m
only once.
n

You'll note that it chokes on the second expect, then jumps into the finally where it get's an illegal state. Thinks it is in replay mode. This is the only test in the class, so the problem does not exist in any other test method.

samples.zip file is missing

Migrated from: CodeHaus issue EASYMOCK-47
Original reporter: Henri Tremblay


I have downloaded the release but the samples.zip file mentioned in the documentation was missing. It was also not available here on sourceforge.

EasyMock doesn't compile in JDK 7

Migrated from: CodeHaus issue EASYMOCK-46
Original reporter: Henri Tremblay


To comply more strictly with the Java specifications, JDK 7 has stopped to allow the following overload:

boolean capture<Capture b) { ... }
T capture<Capture b) { ... }

Can use argument matchers outside of context

Migrated from: CodeHaus issue EASYMOCK-38
Original reporter: Henri Tremblay


Hi,

If somewhere in the test, someone use an argument matcher outside of a easy mock context like a formatService.scale2((BigDecimal) anyObject()); into an integration test, the framework has some strange comportement :
java.lang.IllegalStateException: 1 matchers expected, 2 recorded.
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:56)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:48)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:40)
at org.easymock.internal.RecordState.invoke(RecordState.java:76)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:38)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:72)
at $Proxy5.scale(Unknown Source)
at fr.java.freelance.easymock.CalculServiceTest.testAdd(CalculServiceTest.java:40)
on a method that juste have one argument but the matcher of formatService.scale2((BigDecimal) anyObject()); is still in the matchers'list for the one argument method !

Stackoverflow with toString

Migrated from: CodeHaus issue EASYMOCK-42
Original reporter: Henri Tremblay


When passing an object to a mock in the toString method and the expectation wasn't setup, the call results in a stackoverflow.

I think it would be better to catch this exception and just use the objects classname. An improvement may be to detect, if easymock is processing an expectattion failure and just throw a special exception in the case there is another mock called while calculating toString. This way easymock doesn't have to wait for an stackoverflow to occure.

Example:

public class StackOverflowTest extends TestCase {

public interface IInformationProvider {

public String getName(Wrapper wrapper);

}

public static class Wrapper {

private final IInformationProvider fProvider;

public Wrapper(IInformationProvider provider) {
  fProvider = provider;
}

@Override
public String toString() {
  return fProvider.getName(this);
}

}

public void test_overflow() {
IMocksControl control = createStrictControl();
IInformationProvider mockedInfoProvider = control.createMock(IInformationProvider.class);

control.replay();

new Wrapper(mockedInfoProvider).toString();

control.verify();

}
}

replayAll and verifyAll convenience methods

Migrated from: CodeHaus issue EASYMOCK-15
Original reporter: Henri Tremblay


It would be great to have some convenience methods on the EasyMock class, like these two:
EasyMock.replayAll()
EasyMock.verifyAll()

They would specifically take no parameters, and be the equivalent of calling EasyMock.replay(...) for each mock that has been created in the current test.

array equals not work well in jdk5

Migrated from: CodeHaus issue EASYMOCK-8
Original reporter: Henri Tremblay


            jdbcOperations.update(contains("vbb_user"), aryEq(new Object[] {100, 1 }))).andReturn(1);

code like above will be reported not much

cause jdk auto package 100 and 1 to Integer Object

if replace with code below, will fix it.

            jdbcOperations.update(contains("vbb_user"), aryEq(new Object[] {
                    new Integer(100), new Long(1) }))).andReturn(1);

CodeGenerationException mocking a class in Eclipse plugin

Migrated from: CodeHaus issue EASYMOCK-37
Original reporter: Henri Tremblay


When attempting to mock a class in an Eclipse test plugin (a plugin that tests another plugin), a CodeGenerationException is generated when running under OSGi classloaders (the Run As | JUnit Plugin Test).

This is similar to the bug ID: 2759024, but not quite the same.

There are long descriptions of how JMock solved it: http://jira.codehaus.org/browse/JMOCK-124
and Mockito solved the same issue: http://code.google.com/p/mockito/issues/detail?id=11&can=1

The last comment in the Mockito issue ( http://code.google.com/p/mockito/issues/detail?id=11&can=1#c29 ) looks to be the key to a solution. All about taking care which classloader cglib uses,

stack trace eaten

Migrated from: CodeHaus issue EASYMOCK-4
Original reporter: Henri Tremblay


A bug elsewhere in our code caused an exception while
a test was running, but the source of the error did not
appear in the stack trace. It looks like easymock may
have eaten our stack trace -- this makes it hard to find
the error.

The stack trace was as follows:

java.l
ang.ArrayIndexOutOfBoundsException at
org.easymock.ObjectMethodsFilter.invoke
(ObjectMethodsFilter.java:41) at $Proxy2.update
(Unknown Source) at
ca.uhn.pls.impl.repository.command.RepositoryRemoveFiel
dCommand.execute
(RepositoryRemoveFieldCommand.java:63) at
ca.uhn.pls.impl.CompositeCommand.execute
(CompositeCommand.java:33) at
ca.uhn.pls.impl.AbstractMessageHandler.handle
(AbstractMessageHandler.java:59) at
ca.uhn.pls.impl.MessageDispatcherImpl.doDispatch
(MessageDispatcherImpl.java:142) at
ca.uhn.pls.impl.MessageDispatcherImpl.dispatch
(MessageDispatcherImpl.java:101) at
ca.uhn.pls.adt.handler.AbstractAdtMoveMsgHndTest.test
OneSiteIdExistsAndOneSiteIdMergeExistsInRepositoryMsg
HaveHcnMerge(AbstractAdtMoveMsgHndTest.java:284)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39) at
sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)

It turns out the exception was being raised in the equals
() method of another class, RecordImpl, which doesn't
appear in the stack trace. If we had had perfect JUnit
coverage then another test would have turned this up,
but we don't, so finding it was lucky.

I think this arises from the following line code in
org.easymock.ObjectMethodsFilter.invoke():

try {
return delegate.invoke(proxy, method, args);
} catch (Throwable e) {
throw e.fillInStackTrace();
}

... how about letting the throwable go as-is? I.e.:

return delegate.invoke(proxy, method, args);

That would preserve the whole stack trace as opposed
to just invoke() and below. Is there a reason not to do
this?

Best regards,
Bryan

Expectations on partial mocks are broken

Migrated from: CodeHaus issue EASYMOCK-14
Original reporter: Henri Tremblay


I have a mock of a class, where I have only mocked two methods. I set my expectations - in this case that both of those methods are called - and run my test. This works.

I then started changing things to see the test break. I commented out one of the expectations, but my test still passes. With a strict mock, this should not be the case; it should fail, as a method was called that the mock was not told to expect.

This is also the case with 2.3.

Add method to find control for object

Migrated from: CodeHaus issue EASYMOCK-48
Original reporter: Henri Tremblay


I am currently using EasyMock, and am deep within some
code, setting up a test case. Unfortunately, at this
point, I have access to an object returned by
getMock(), but not to the MockControl that created it.
In order to write the test, I need access to the control.

I have a couple suggestions on how this could be
accomplished.

One:

Have each object that is returned by getMock()
implement an interface (say IMockObject), which would
have a method named getControl(). Then each object
would have a link to the MockControl that created it
and would return it from that call.

Then, in my code I could simply do:

MockControl control = ((IMockObject) object).getControl();

Two:

Have MockControl keep a Map of controls that have been
created, with the objects as keys and the controls as
values. Then add a method to seach this map and return
the object.

Here's the code you would need to add:

a) Add to the class a new static member:

private static HashMap CONTROL_MAP = new HashMap();

b) In the reset() method, add

CONTROL_MAP.put(mock, this);

c) In the verify() method, add

CONTROLMAP.remove(mock);

d) Add two new methods:

public static MockControl getControl(Object key)
{
return (MockControl) CONTROL_MAP.get(key);
}

public static void clearControls()
{
CONTROL_MAP.clear();
}

Since reset() is called from the constructor, that
ensures that each object is inserted into the map. The
addition to the verify() method removes objects that
are no longer needed. As would a call to the
clearControls() method.

The main drawback to the second method is that if
someone uses a lot of control objects, but doesn't
verify them or clear the controls, things can stack up.
To mitigate that, you could make mapping optional,
adding enableMapping() and disableMapping() methods,
with the default being disabled.

The first solution doesn't suffer from that problem.
Unfortunately, I don't understand how the code works
well enough to write the code for you.

Class mocking not working for Eclipse plugin-in test

Migrated from: CodeHaus issue EASYMOCK-45
Original reporter: Henri Tremblay


When using class mocking in a simple Eclipse JUnit plug-in test, and error occurs.
In plugins folder I have added additional bundles:

easymock-3.0.jar
com.springsource.net.sf.cglib_2.2.0.jar
org.objenesis_1.2.0.jar

Two sample projects which can be used to reproduce the problem are attached, simply import them in Eclipse and run EasyMockClassMocking/test.EasyMockTest from Run-as->JUnit plug-in test . Also I used 3 additional bundles, in my Eclipse plugins folder I have added:

http://ondex.rothamsted.bbsrc.ac.uk/nexus/content/groups/public/net/sourceforge/cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar
http://easymock.org/maven/repository/org/objenesis/objenesis/1.2/objenesis-1.2.jar
http://easymock.org/maven/repository/org/easymock/easymock/3.0/easymock-3.0.jar

Error that is triggered by EasyMock:

net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
at org.easymock.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:190)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:60)
at org.easymock.EasyMock.createMock(EasyMock.java:104)
at test.EasyMockTest.testClassMocking(EasyMockTest.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62)
at org.eclipse.pde.internal.junit.runtime.CoreTestApplication.run(CoreTestApplication.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:587)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:198)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
... 47 more
Caused by: java.lang.NoClassDefFoundError: test/ProductiveClass
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
... 53 more
Caused by: java.lang.ClassNotFoundException: test.ProductiveClass
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 56 more

Cheers,
Petar

capture(Capture) only captures last method call

Migrated from: CodeHaus issue EASYMOCK-10
Original reporter: Henri Tremblay


Code sample:

SomeObject obj = createMock(SomeObject.class);

Capture cap1 = new Capture();
Capture cap2 = new Capture();

obj.doSomething(eq("test"), capture(cap1));
obj.doSomething(eq("anotherTest"), capture(cap2));

replay(obj);

obj.doSomethingToCauseMethodCalls();

verify(obj);

Problem:

The object returned from cap1.getValue() == cap2.getValue(). Or - to be more precise - no matter which capture object you use the only value returned from getValue() will be the last captured value.

Probably some static state thing but didn't seem like this is what you guys intended.

in some cases replay chooses the wrong matcher

Migrated from: CodeHaus issue EASYMOCK-33
Original reporter: Henri Tremblay


I have an example of a mock that calls the same method twice.
Each time has a different matcher registered.
In some cases, the mock replay uses the first matcher for the second invocation, but not in all cases.
See attached.

StubReturn does not capture any values

Migrated from: CodeHaus issue EASYMOCK-26
Original reporter: Henri Tremblay


Capture capturedSelectExample = new Capture();
List list = new ArrayList();
list.add(new MyClass());
expect(mockMyClassDao.selectMyClassByExample(and(isA(MyClassExample.class),capture(capturedSelectExample)))).andStubReturn(list);
replay(mockMyClassDao);
...
MyClassExample capturedResults = capturedSelectExample.getValue();
...
verify(mockMyClassDao);

this throws 'Nothing Captured' when using .andStubReturn(...) but works just fine when using .andReturn(...); I would prefer to be able to use .andStubReturn and still be able to capture.

Stub exception causes NPE

Migrated from: CodeHaus issue EASYMOCK-17
Original reporter: Henri Tremblay


Versions Affected:

EasyMock Class Extension 2.3 and 2.4

Scenerio:

When using EasyMock ClassExtension to create a stub version of an exception type that is thrown during a test by a mock collaborator of the class under test, EasyMock itself generates a NPE, instead of throwing the stub exception from the mock collaborator.

Example:

See attached. Can be run as a TestNG or JUnit test case.

Current Workaround:

When setting up the stub exception, include the following behavior:

EasyMock.expect( exception.fillInStackTrace() ).andReturn( exception );

Possible Solution:

Check whether the Throwable returned by t.getThrowable() is itself a mock object. If so, skip the fillInStackTrace() call before rethrowing it.

No error when setting expectation on an "unmocked" method

Migrated from: CodeHaus issue EASYMOCK-25
Original reporter: Henri Tremblay


On a partial mock, if you wrongly set and expectation on a method that isn't mocked:

  • The real method gets called
  • Later, the recording will break but the error message is misleading

The error should be thrown right away and with a meaningful message.

Incorrect behaviour for andStubReturn()

Migrated from: CodeHaus issue EASYMOCK-41
Original reporter: Henri Tremblay


In EasyMock 1.x you could use setDefaultReturnValue() to stub a default return value for a method call but you could also change the default return value by simply calling setDefaultReturnValue() again, with a new value. We have over 20000 tests and a significant number of these make use of this "feature". Notably, in a call to reset, we often reset the default return value for various state machines, but from time to time we may need to state to be different at the start of a test. We achieve this by then setting then default value for the same method call with a new value. From EasyMock 2.x onwards, this is no longer possible to set the default return value/stubbed return value multiple times with different values between calls to reset.

I had a look at the source for 2.5.2 specifically and noticed that the MocksBehaviour.addStub() does not look for an existing expected invocation before adding a new invocation and result object. This in itself is not wrong, but the MocksBehaviour.getStubResult() is iterating through the list of stubbed values and returning as soon as it finds the first one! This would seem to indicate that there should be only one stubbed value per mock method call.

I offer the attached SVN patch file for your consideration that will enable MocksBehaviour.addStub() to determine if an existing invocation and result exists and replace the stubbed result if applicable. This would re-enable the 1.x functionality and eliminate the ability to add multiple redundant stubbed values.

RuntimeException on failing verify if mock is instrumented

Migrated from: CodeHaus issue EASYMOCK-31
Original reporter: Henri Tremblay


org.easymock.internal.Invocation#toStringIsDefined:
"throw new RuntimeException("The toString() method could not be found!");"
has to be replaced with
"return false;"

Now Easymock throws this RuntimeException on such a trivial error instead of just ignoring it.

I'm using PowerMock in order to instrument the mock ("final" removed from class declaration).
So the Mock is generated by CGLib and doesn't declare toString itself.
And that's why EasyMock fails here.

Capturing parameters from single argument methods

Migrated from: CodeHaus issue EASYMOCK-13
Original reporter: Henri Tremblay


First off, I'm very happy with EasyMock, it has saved me many hours of work.

Not sure if this is a bug or intended behaviour.

Having read bug 2060545
However, EasyMock behavior is perfectly normal. Captures doen't occur in
order. They occur when a call is matched.

What should happen in the case of a mock method with a single parameter that is called twice?

import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.easymock.Capture;
import org.junit.Test;

public class MultipleCaptureTest {

@Test
public void testCaptureNonStrictControl(){
    /*
     * Should multiple same-type captures be allowed when order is 
     * not enforced?
     */
    testCaptureHelper(createMock(IProcess.class));
}

@Test
public void testCaptureStrictControl(){     
    testCaptureHelper(createStrictMock(IProcess.class));
}

@SuppressWarnings("unchecked")
protected void testCaptureHelper(IProcess processMock){
    Capture<?> capture1 = new Capture();
    Capture<?> capture2 = new Capture();

    processMock.process(capture(capture1));
    processMock.process(capture(capture2));

    replay(processMock);
    processMock.process(new Object());
    processMock.process(new Object());
    verify(processMock);

    assertTrue(capture1.hasCaptured());
    assertTrue(capture2.hasCaptured());
    assertFalse(capture1.getValue() == capture2.getValue());
}

public interface IProcess {
    public void process(Object object);
}

}

Perhaps something like this would work....

public class Captures implements IArgumentMatcher, Serializable {

private static final long serialVersionUID = 1L;

private Capture<T> capture;

public Captures(Capture<T> captured) {
    this.capture = captured;
}

public void appendTo(StringBuffer buffer) {
    buffer.append("capture(").append(capture).append(")");
}

@SuppressWarnings("unchecked")
public boolean matches(Object actual) {
    /*
     * If the capture has already been done then this capture
     * cannot be used
     */
    if (!capture.hasCaptured()){
        capture.setValue((T) actual);
        return true;
    } else {
        return false;
    }
}

}

Although this breaks one of the unit tests...

Allow passing wrapper for primitive to setReturn

Migrated from: CodeHaus issue EASYMOCK-49
Original reporter: Henri Tremblay


I have a case where I am testing a bunch of calls and I
am not handcoding the mocks for each but am using
reflection to make the calls to create and set up the
mocks. But there is a bit of a problem for setting the
return value for primitives. If I had a method that
returns boolean for instance, it appears that the only
way to set the return value is something like:

control.setReturn( booleanValue );

where booleanValue is a primitive boolean expression. I
would like it to also allow

control.setReturn( BooleanObject );

where BooleanObject is an instance of the Boolean
wrapper class.

The reverse should also be true that it will accept
primitive when the return type is of a wrapper class.

Mocking equals results in next test failing also

Migrated from: CodeHaus issue EASYMOCK-30
Original reporter: Henri Tremblay


We are using EasyMock (and ClassExtensions) in our test framework. A co-worker tried to mock equals (I later told him that was not neccessary) and got some funny results. Not only his actual test failed, the next executed test also failed. EasyMock seems to remember that there was a aborted recording and doesn't reset its state.
Attached are examples for EasyMock and Class Extensions.

Thank you and best regards
Marcel Freese

Wildcard generics problem

Migrated from: CodeHaus issue EASYMOCK-9
Original reporter: Henri Tremblay


Following code is not compiling:

public class SomeTest
{
public static interface A
{
public Class<?> get();
}

@test
public void testSomething()
{
A mock = EasyMock createMock(A.class);

EasyMock.expect(mock.get()).andReturn(String.class);
replay(mock);

}
}

Error message is as follows:

The method andReturn(Class<capture#2-of ?>) in the type
IExpectationSetters<Class<capture#2-of ?>> is not applicable for the arguments
(Class)

To make it valid I need to change Class<?> to raw type Class. Then it works.

Obviously following code is perfectly valid:

public class StringA implements A
{
public Class<?> get() { return String.class; }
}

Migrate build to Maven 3

Migrated from: CodeHaus issue EASYMOCK-1
Original reporter: Henri Tremblay


Currently the build isn't compiling with Maven 3 because of the maven-clover-plugin.

This should be fixed to get the benefits of Maven 3.

Can't delegate to a protected method

Migrated from: CodeHaus issue EASYMOCK-28
Original reporter: Henri Tremblay


If a protected method is mocked and then the result is delegated to an implementation, the call fails.

Something like below in Result.DelegatingAnswer should do the trick

      Method m = invocation.getMethod();
      m.setAccessible(true);
      return m.invoke(value, invocation.getArguments());

IllegalAccessError for Package-Scope-Interfaces

Migrated from: CodeHaus issue EASYMOCK-20
Original reporter: Henri Tremblay


When you declare a Interface to be accessible only inside a package and setup a proxy in a test using a parallel package hierarchy, the proxy throws a IllegalAccessError on the first call:

java.lang.IllegalAccessError: tried to access class plugin.operation.cleanup.IElementCleanup from class $Proxy2
at $Proxy2.createCleanup(Unknown Source)
at ModelCleanUp.cleanupAndValidate(ModelCleanUp.java:35)
at plugin.operation.cleanup.ModelCleanUpTest.test_validateAndCleanup(ModelCleanUpTest.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

interface IElementCleanup {
public boolean createCleanup(IElement element);
}

@test
@test
public void test_validateAndCleanup() {
IElement element1 = fControl.createMock("element1", IElement.class);
IElementCleanup cleanup = fControl.createMock("cleanup", IElementCleanup.class);
fControl.replay();
ModelCleanUp.cleanupAndValidate(cleanup1, element1, element2, element3);
fControl.verify();
}

Nicer handling of recordings with params partially matched

Migrated from: CodeHaus issue EASYMOCK-27
Original reporter: Henri Tremblay


EasyMock requires to have no matcher or a matcher for each parameter during a method recording.

There should be a nicer error message or a way to workaround that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.