07 November 2013

New to Git. Used to SVN.

Some random thoughts about moving to "git" from "SVN":

In git, when they talk about branches and draw those little diagrams with circles and lines to show branching, it is incredibly complex because git encourages branching.

When you do a commit on your local copy of the repo, it creates a new thing that is called a branch according to the way git thinks.

They draw pictures like this:

Each circle is what happens when there is a git commit and is called a branch. 

In SVN its just a sequence of commits and they tend to be called versions or revisions. In SVN they have numbers (in sequence) but the branches are named with their own sequence of numbers.

In git, they also talk about the contents of a branch which seems to mean all the changes that comprise the branch.

30 November 2012

Context in Javascript regex replace with anonymous function

I know. The title is a killer. I'm only putting this post here since I couldn't find this information anywhere.


First, lets talk about the 'replace' function on Javascript strings. Here's an example with a search for a string.


var name= "World";
var msg = "Hello name!";
var result = msg.replace("name", name);

This results in:

Hello World!


Now, you can use a regular expression (and, in fact, probably should) in place of the string. The yellow highlight shows what you change to make it a regular expression. (I'm not going to define regular expressions. I'm trying to get to my real concern in this particularly wordy way.)

var name= "World";
var msg = "Hello name!";
var result = msg.replace(/name/, name);

This results in the same thing:

Hello World!


Of course, we can use the regular expression to search for something more complicated. In this case, it will find one or more vowels between the 'n' and the 'm' in 'name' and match the whole word.

var name= "World";
var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/, name);

This results in the same thing three times even though the starting strings contained different vowels. Oh, no, it doesn't. It only replaces the first occurrence:

Hello World! Hello nime! Hello nouiame!


We get the result we want if we add the 'g' option to the regular expression.

var name= "World";
var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/g, name);

This results in the same thing three times even though the starting strings contained different vowels and it really works:

Hello World! >Hello World! Hello World!


Finally, getting close to what this blog entry is about. It concerns you when you have a block of Javascript like this. You are replacing multiple instances of some matched regular expression using a function to generate the replacement string. In this case we will reverse the original string and include that in the replacement.


var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/g, function(matched) {
    return "World (" + matched.split("").reverse().join("") + ")";
});

This results in the same thing three times even though the starting strings contained different vowels. Oh, no, it doesn't. It only replaces the first occurrence:

Hello World (eman)! Hello World (emin)! Hello World (emaiuon)!


Finally, what I want to comment on. Again we will reverse the original string and include that in the replacement. But lets put it in a function and get the "World" from a variable that is in the same context.

{
    worldString : "World",
    myFunction: function() {
        var msg = "Hello name! Hello nime! Hello nouiame!";
        var result = msg.replace(/n[aeiou]+me/g, function(matched) {
            return this.worldString + " (" + matched.split("").reverse().join("") + ")";
        });
        return result;
    }
}

This should result in the same thing (You know, three times.) But it actually fails because the context of the function called by "replace" is the main 'window' object. Here is what Chrome (Version 23.0.1271.64 m), IE 9 and FireFox (16.0.2) shows:

Hello undefined (eman)! Hello undefined (emin)! Hello undefined (emaiuon)!

Here is a jsfiddle showing this fail and the success


So, what works? We do put it in a function still and we get the "World" from a variable that is in the same context. But we have to save the context in "myFunction" and use it in the anonymous function:

{
    worldString : "World",
    myFunction: function() {
        var self = this;
        var msg = "Hello name! Hello nime! Hello nouiame!";
        var result = msg.replace(/n[aeiou]+me/g, function(matched) {
            return self.worldString + " (" + matched.split("").reverse().join("") + ")";
        });
        return result;
    }
}

This does result in the three times we expected last time:

Hello World (eman)! Hello World (emin)! Hello World (emaiuon)!

Here is the same jsfiddle showing the fail and this success




25 March 2011

Maven Checkstyle Reports Shortcut

I'm using Maven 2.2.1 today. MyEclipse version is 8.5.

When you want a Checkstyle report from Maven 2 you need to put these two bits of xml in your pom.xml. Then you need to create the Checkstyle.xml and license.txt files.

Be sure to check what the right version is of the plugin. Its shown at the bottom of the page: maven-checkstyle-plugin You might have to back off one version.

<build>
    <pluginManagement>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>2.6</version>
            </plugin>
            ...
         </plugins>
    </pluginManagement>
</build>

and then put the report request in. (Be sure to put it after the JXR report if you are using that one. There is some report that needs to be after JXR and it might be Checkstyle. I can't remember for sure but we all have our little superstitions.)

<reporting>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <configuration>
                <enableRulesSummary>false</enableRulesSummary>
                <configLocation>${basedir}/Checkstyle.xml</configLocation>
                <headerLocation>${basedir}/license.txt</headerLocation>
                <excludes>**/generated-sources/**/*.java</excludes>
            </configuration>
        </plugin>
        ...
     </plugins>
</reporting>

You may (or may not) want the "enableRulesSummary" option off. I find it obnoxious to have all that page space taken up by the long explanations.

The "license.txt" file is the easiest. You only need it if you are going to have a rule that checks for a certain header at the top of each .java file. You can change the name but be sure to use the real name when setting up the Checkstyle rules that you want to use.

Now, for the rules file -- Checkstyle.xml. There is an easy way to create this file. Much easier than typing a bunch of cryptic XML into an editor. We just let the Eclipse do it.

You have to have the Eclipse Checkstyle plugin installed. I've done it multiple times with multiple versions of Eclipse and multiple versions of the Checkstyle plugin. Once you have that plugin installed, use the Eclipse preferences menu item to bring up the preferences box. Find the Checkstyle entry in the left section of the box and click it.

This will bring up the Checkstyle preference. Create a Checkstyle configuration of your own. Or you can use the built-in Sun configuration as a start and fool around until it tells you enough but not too much. That's always the problem with code analysis tools. When you first run them on some code, they complain about all sorts of things that you just don't care about.

Maybe your code has curly-braces in the "wrong" place and you don't really care. Change the rule settings to ignore placement of the curly-braces. So, click about 1000 times and get all the Checkstyle rules set up as you like.
On a side note: I have found that using the Checkstyle Eclipse plugin together with the Eclipse Code Formatter you can sort of play the tools off against each other for code format issues.
Most groups of developers have some sort of code-format conventions. Whatever it is, most everyone dislikes some aspect of it. But if you supply them all with a code formatting template created to be used in Eclipse and exported to a file, they can use it just before submitting code.
They can type however they want. They can even format it to their own preferences while working on it (for the fussy programmer). Just fix it before putting the code away. Then use Checkstyle to see if they are doing it. You can make a build fail if the format is wrong but I find that obnoxious. Just create a report somewhere that the managers or team leads can look at and complain now and again. In real life, most everyone just gets used to it unless they are working on multiple sets of code with different rules.
Anyway, put the formatting rules in your Eclipse and format a large body of code. Do that by right clicking on a source folder and finding "reformat" on one of the nested menus. Then let Checkstyle, also inside Eclipse, check it.and see what the errors are. You will probably end up changing both configurations until you get it right.
Whatever the rules, when you have them "right," you can just export the rules with the button on the Checkstyle preferences page. Store them, if you want to use my pom XML as shown above, in the same folder that the pom.xml file is in and name that export file "Checkstyle.xml" matching the letter case. (Windows doesn't care but you'll thank me for that suggestion if you ever build under Linux.)

The trick is that the "export" stores the file in exactly the format that Checkstyle's Maven 2 plugin wants (or even the same format that Checkstyle's ANT task wants). I keep Checkstyle.xml with the project code, store it in my version control and now and then make a few changes.

The thing is, as time goes by you either get tired of seeing some of Checkstyles complaints that you thought you cared about. Or you decided to ratchet it up a notch and add some more checks because the code is better than it used to be or because the team is getting into some bad habits that you'd like to nip in the bud.

For example, I worked with a team once and a couple of guys couldn't find it in themselves to put a debug logging statement in the code they were working on. They had to put a "System.out.println()" call in there and, of course, they would forget to remove them all. We added a custom regex rule to Checkstyle that said "System.out" and "printStackTrace(" were illegal to use in the code. We had to live with a few complaints here and there where we really wanted to output to the console. One was a little utility that just lived in the code but ran from the command line. The other was where everything went horribly wrong during startup and we needed a message but the logger wasn't set up yet. So we found all the funky debug lines and had the offenders (who we identified from the checkin records) remove them or change them to use the logger.

Once you save the export file, you run "mvn clean site" to generate the report.

If you have a site deployment location set up in the pom.xml you can then do "mvn site:deploy". Note that I have found you shouldn't do these three targets all together. Do the clean-site first and then do the site:deploy. It just works better that way.

04 November 2010

GWT StockWatcher and MyEclipse

I did the Google Web Toolkit tutorial creating the StockWatcher application. I don't know if there are more tutorials that build on this but the one at THIS PLACE creates an application in Eclipse and shows you how to compile it to a bunch of html, css, js and such files. The logic in this example all ends up in the javascript that is generated from the java the tutorial helps you create (or lets you copy and paste). [Note that you can do the tutorial without Eclipse but this article has "MyEclipse" in the title.]

I used MyEclipse version 8.6. I downloaded their Pulse tool sometime back and used it to build myself a new profile that included MyEclipse 8.6 (based on Eclipse 3.5 - Helios). Subclipse, Checkstyle and the Google Plugin for Eclipse. If you already have one of the 8.x series MyEclipses installed, you can probably use the included Pulse-like facility to create the new "profile". (For those unfamiliar with MyEclipse, a "profile" in Pulse is a collection including one version of Eclipse or MyEclipse and zero or more plugins. When you get it loaded on your computer, its simple another instance of Eclipse that can be run alongside any other Eclipse versions you have on your machine.) Also, you don't need Subclipse or Checkstyle installed to do the tutorial or what I describe below. I just always include them in my profiles.

You could probably do all this with a pure Eclipse version with the Google Plugin for Eclipse installed. But you would have to run Tomcat separately and build and deploy the war as described below. The feature of running Tomcat inside Eclipse and doing easy deployments is a MyEclipse feature. (But there may be other plugins that can do this independently but similarly.)

Sidebar: Note that to add the Google plugin to my Pulse profile, I could not simply select the Google plugin like I did with all the other plugins. I found a note on the web somewhere that explained how to do it. Find the information on the plugin by Googling for GWT. This will tell you the Eclipse update location that matches the version of Eclipse you are using. I found it at http://code.google.com/eclipse/docs/getting_started.html where it shows that the update location for Galileo is http://dl.google.com/eclipse/plugin/3.5 and chose, within Pulse, to "add an update site" which is a tiny link just to the right of a title near the top of the page. Enter the update location and save. A new entry appears allowing you to select the "Google Plugin for Eclipse" under that new entry. And there you go.

So, using my brand new MyEclipse 8.6 installation, I proceeded to open it up and select a location for the workspace.

Next I went through the whole tutorial to create the StockWatcher "application" and compile it.

When it compiles, it goes into a folder off the root of your Eclipse project that is named "war." That folder gets filled with all the results of the compilation and can be run, if you have deployed it in development mode you can run the compiled version by removing the query part of the URL used to access the app for debugging and development. In my case that URL was http://127.0.0.1:8888/Stockwatcher.html?gwt.codesvr=127.0.0.1:9997 and, removing the query part is http://127.0.0.1:8888/Stockwatcher.html.

But I wanted to run it in the Tomcat that is supplied with MyEclipse. Here's how to do that:

1) Since I had a whole new MyEclipse installation, I had to configure the Tomcat. You do this by going to the MyEclipse property page at Window > Preferences > MyEclipse > Servers > Integrated Sandbox > Tomcat. I only changed the port it runs on to 8090 so it wouldn't interfere with Google's development "server" (really an instance of Jetty included somewhere). Save all that.

2) Configure the project to deploy correctly. First, right click on the project itself and choose MyEclipse > Add Web Project Capabilities. Set the web root to the "war" folder that holds all the compiled artifacts for StockWatcher. Save this setting. When you do, it will complain about the folder to which Eclipse is set to store the compiled java class files. Click "Yes" you would like to change that folder to be inside the "war" folder you just selected.

3) You need to change the "deployment" options for the web application. So, reopen a similar dialog box to the one in step 2 above, by going to the project properties for your project and opening the web entry under MyEclipse. (Select the project. From the menu bar do Project > Properties > MyEclipse > Web)

4) Open the "deployment" tab (the rightmost one) and DON'T use the default settings for Web Project Deployment Policies. Instead, click the "ignore" option to "do it yourself", which means you will do nothing. Also, DON'T use the Library Deployment Policies default setting. Instead, unclick everything there. (Note that you may need to select some of those options judiciously if you are deploying a different web app that uses back-end, server based code requiring some 3rd party jars. Remember that StockWatcher, at this point, only has JavaScript and no back-end code at all.) Save all that.

5) There are two ways to add a deployment for Tomcat and your StockWatcher project. You can approach it from either the project deployments direction or the Tomcat deployments direction. I like the latter. So click the tiny arrow beside the icon for "run/start/remove MyEclipse deployments" that looks like a little desktop/tower computer box. (Funny how people have taken to calling those the "hard disk.") The options drop down and you click "Manage Deployments". When the box opens, select "Tomcat" in the top drop-down box labeled "Server" and then click the "add" button at the right. Select your project from the drop down list. You may want to choose exploded war or not. Then save it. (The other way starts by right-clicking on the server itself in the "Server" view ...)

6) You might see some lines from the Tomcat console display.

7) Go to your browser and open up "http://localhost:8090/stockwatcher/StockWatcher.html" or similar URL depending on what, exactly, you named things. If you don't know what to use for the html file name, look in the "war" folder in your project. It will be there. If you don't know the application context (which is the 1st part of the url after the port number), you approved it and maybe entered it on the project properties myeclipse web page on the left tab where it says "context root."

There you go. Now you have the StockWatcher application running on the Tomcat inside MyEclipse.

If you want to create a .war file that can be deployed on an independent Tomcat (or other JEE server) you can right click on the project name, select Export, choose the project again, browse to a folder and supply a .war file name and, finally, click "Finish". The .war file will get put where you choose and can be deployed however your server deploys apps. (For Tomcat, drop the war file into the "webapps" folder and that usually does it.)

Addendum: I followed through with the additional tutorial at http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html and found that these same steps work to deploy the StockWatch example with RPC back-end code included.

25 February 2010

Auto-Install Maven into Hudson

It turns out to be easy to have Hudson download a version of Maven for you to use in your builds.I Googled for instructions and found none but then any Google for anything about Hudson is likely to find the river, the explorer or Jennifer.

I'm using Hudson 1.336 as I write.

You may need to figure out how to set up a proxy if your Hudson server is inside your companies network boundaries. The following instructions assume you have already got that working. I find the whole proxy issue confusing as there is a way documented to enter a proxy when deploying to a repository and a way to enter a proxy that is sort of hidden when updating plugins. I haven't seen one related to downloading tools.

1) Click on the "Manage Hudson" link on the top page.
2) Click on the "Configure System" link at the top of the list in the main part of the page.
3) Scroll Down to the "Maven" section and click the "add Maven button" as in the red circle below
4) Select "Add Installer"
5) The drop down list of install from options has an option "tar.gz" you should select.
6) "Label" field is blank. I don't know quite what this does.
7) Enter a link to one of the apache mirrors like: "http://mirror.uoregon.edu/apache/maven/binaries/apache-maven-2.2.1-bin.tar.gz" but you can pick your own mirror by opening another browser tab and going to "http://maven.apache.org/download.html" and clicking on the link for the tar.gz file in the "mirrors" column. I picked the one at the top of the top section on that page but you may want a not-latest version. That takes you to the page where it allows picking a mirror. Copy one of the mirror links for the site close to you. The link above is the one I picked.
8) The subdirectory will be like "apache-maven-2.2.1" with the main folder name from the tar.gz file you pointed to. Note that older versions of Maven (for example 2.0.7) are like "maven-2.0.7" and newer ones add the word "apache" to the front. This subdirectory is added to the root folder of where-ever Hudson puts tools that it downloads to produce the MAVEN_HOME value Hudson passes to Maven for builds using this Maven version.
9) Save the configuration changes with the button at the very bottom of the page (or just hit 'enter').

At this point in the process, I was left wondering when it would get downloaded and installed.

10) Create or edit an M2 build to use the new Maven version you just added. When it first runs, the tool will be added to a "tools/maven" folder inside your hudson folder structure AND THEN the build will kick off. (This might work with some other type of build but I haven't tried it.)

01 December 2009

Hudson updates, Linux and the corporate proxy

My Hudson build server is running on Red Hat Linux. This became important when I figured out that I couldn't update Hudson automatically because of some sort of proxy problem.

I would select Manage Hudson > Manage Plugins and then select a plugin or two to update and click the "Install" button to do it. It would give me an error "NoRouteToHost" and show a Java stack trace.

First Try

I was running Hudson 1.309 and, though it might be a bug in that version (but don't quote me on that), entering the corporate proxy server's IP and port on the "advanced" tab of that "Manage Plugins" page didn't fix the problem. (There was a wierd bug where, if I used FireFox 3 to enter the proxy info, it would default the user and password to those I used to log into Hudson. This didn't happen on IE 6.)

This seemed to make no difference at all. The same error popped up as before.

Second Try

I use the command line to start Hudson. Its a command like "java -jar ..." with a zillion options included. So I added "-Dhttp.proxyHost= and -Dhttp.proxyPort=" to the command line.

This had a different result. The plugin upload would work but Hudson could no longer access my Subversion server. The error message appeared in the console log when a job would run but it still said "No route to host".

Third Try

Well, I thought, I will need to exclude the Subversion server from Java's proxy information. This should have worked by adding "-Dhttp.nonProxyHosts=*.domain.com" to the command line.

This didn't work either. I don't know why not but the errors were the same as in the 2nd try.

I took all that stuff off the command line.

Fourth Try

Now, I though, isn't there some way to tell Linux about a proxy to use by adding an environment variable of some sort. I had to Google around to find it. You add an entry to the environment with a command like "export HTTP_PROXY=http://proxy.domain.com:8080/" if you are just typing. I left off the "export" part for the shell script that starts Hudson running.

This worked. Things would update inside Hudson. The jobs can get to the Subversion server. All seems to be cool now.

Disclaimer

I don't claim to know why the last method worked. I don't know if it would work the same way if I was using Tomcat to run the hudson.war. I don't know if the "advanced" tab's proxy settings work better in a later release of Hudson.

All this ignorance on my part bothers me. But, for now, I'm just happy it works.

-- Lee

20 August 2009

JMock vs. Mockito


I heard about Mockito, a new-to-me framework for writing unit tests with Mock objects, and decided to take it for a spin. Below I have shown the same test written with JMock (version 1) and Mockito (version 1.8).

Now, I know that JMock version 1 is old but the real tests for the real code have to run in Java 1.4 so that's the version we tend to use.

Here is the situation:

* I have a list of "alerts"
* Each alert is a simple form of a canned message. The object contains an email address, a message name and some parameters that are used to fill in the blank spots in the message.
* Each parameter is just a name-value pair.
* The message may have some of the names encode in it's text and, for each recipient, his own parameter values are filled in.
* I have to validate the alerts in several ways. The class to do one of those validations is the class under test.
* The validation process is to look through the list of alerts and throw out any that aren't valid. The reason they are invalid is coded into the particular validator class's code.
* Validations can be chained so this validator can have another validator injected that will be called to do further validations when this one is done.
* The validator that is being tested checks whether the exact same alert was previously sent to the same person. (It compares the parameters, message name and recipient to see about that.) It does this by looking for a matching alert in a database containing recently sent alerts.
* If it finds that the alert is a duplicate of one recently sent, it updates the date in the database to indicate an attempt was made today to send it again.
* Some other code fills the database after the alerts get sent successfully.
* Some other, other code cleans out old records from the database to give definition to the term "recent."

So, we are testing the AlertDuplicateRemover so here is one test to see what happens when there is one alert in the list and it is a duplicate.

JMock first:


public final void testStoreSentAlertsDuplicated()
{
int alertCount = 1;
AlertResultBO alertFeed = AlertBOMother.getAlertWithValidParms(alertCount);

Mock duplicatesDaoMock = mock(AlertDuplicatesDao.class);
for (int i = 0; i < alertCount; ++i)
{
duplicatesDaoMock.expects(once()).method("get").with(eq(alertFeed.getAlerts()[i])).will(
returnValue(alertFeed.getAlerts()[i]));
duplicatesDaoMock.expects(once()).method("update").with(eq(alertFeed.getAlerts()[i]),
isA(Calendar.class));
}
AlertDuplicatesDao duplicatesDao = (AlertDuplicatesDao)duplicatesDaoMock.proxy();

Mock validatorMock = mock(AlertValidator.class);
validatorMock.expects(once()).method("validate").with(isA(AlertResultBO.class)).will(
returnValue(alertFeed));
AlertValidator validator = (AlertValidator)validatorMock.proxy();

AlertDuplicateRemoverImpl remover = new AlertDuplicateRemoverImpl();
remover.setAlertValidator(validator);
remover.setAlertDuplicatesDao(duplicatesDao);

remover.validate(alertFeed, CalendarMother.yesterday());
}


And then Mockito


public final void testStoreSentAlertsDuplicated()
{
int alertCount = 1;
AlertResultBO alertFeed = AlertBOMother.getAlertWithValidParms(alertCount);

AlertDuplicatesDao duplicatesDao = mock(AlertDuplicatesDao.class);
when(duplicatesDao.get(alertFeed.getAlerts()[0])).thenReturn(alertFeed.getAlerts()[0]);

AlertValidator validator = mock(AlertValidator.class);
when(validator.validate(any(AlertResultBO.class))).thenReturn(alertFeed);

AlertDuplicateRemoverImpl remover = new AlertDuplicateRemoverImpl();
remover.setAlertValidator(validator);
remover.setAlertDuplicatesDao(duplicatesDao);

remover.validate(alertFeed, CalendarMother.yesterday());

verify(validator, times(1)).validate((AlertResultBO)any(AlertResultBO.class));
verify(duplicatesDao, times(alertCount)).get((AlertBO)any(AlertBO.class));
verify(duplicatesDao, times(alertCount)).update(any(AlertBO.class), any(Calendar.class));
}


Notes on the code:

AlertBOMother - I got the idea for this from Derek Lane a few years back. Its a class used only for testing. It has static methods that return prepopulated objects so that multiple tests can just ask for one. Its particularly useful to clean up all that code where you fill in an object's properties. Using the "Mother" hides that away so it doesn't clutter the test (and hide what its testing). It also makes the prefilled object available for multiple tests without using RBCAP (reuse by cut and paste). When properties for the object change or are added, using a 'mother' makes it easy to adjust the tests. Finally, it makes it easy to start your testing with a simple version of the object and then improve the contents used for testing later.

Both mock the DAO that is used to read (get) and update the database records. 'get' is used to see if the alert is already there (implying it was already sent). A null is returned if no match is found in the database.

Both also mock the other validator to which this validator chains after working its magic.

The mocks, in both cases, are injected into the class-under-test as they would by by Spring in real life. That class knows nothing about Spring so there is no need to call any of Springs special methods to do Spring stuff.

Mockito code seems a little simpler. There is a bit less clutter to hide the intent of the test.

I never did like how JMock has you put a method name in a string. Mockito doesn't do this.

JMock sets up the expectations ahead of time. Mockito checks the expectations after the fact. That makes Mockito more like the way JUnit works. In both, you do stuff and then see if the results are right.

JMock sort of mixes up the expectation code and the setup code. Let me explain. There is code to tell the mock object what to do. That's what I call 'setup code'. Three is code to check that the expectations of what happened during the running of the code really happened. That's the 'expectation code.' Notice that in JMock, both types of code preceed the test and are mixed together. In Mockito the setup preceeds the test and the expectations follow it.

Interestingly enough, running inside Eclipse 3.3 under Java 6, the Mockito tests took twice as long to run as the JMock tests. This is the time for all the tests not just the one test shown above. The difference was only 1/2 second in this case but it could add up. I'm not sure how much it matters as I find that only about 10-15% of my tests need mocks anyway. (But, maybe I need to write more tests.)

Neither framework has very good documentation. In both cases, it consists of a few pages of examples and some javadoc. (I should note that I'm talking about JMock 1 here. The docs for JMock 2 may be better.) JMock is here http://www.jmock.org/index.html and Mockito is here http://mockito.org/

Finally, I don't pretend to be an expert in either framework. I've been using JMock on and off for 4 years on several projects. This is my first attempt with Mockito.

I'm sure there are better ways to use both and one or the other may shine when the tests are more complicated. (On the other hand, complicated tests are a pain in the ... neck and I really like simple ones better.)