Assert Property Equality

When you start doing more thorough testing of your code you will quickly find that the existing JUnit functionatly is not always robust enough to relieve some of the tedium in testing. Let’s take for instance a simple equals method for a person object.


public boolean equals(Object o) {
   Person person = (Person) o;
   Boolean isEqual = true;

   isEqual &= (firstName == null && person.firstName == null) || (firstName != null && person.firstName != null && firstName.equals(person.firstName);

   isEqual &= (lastName == null && person. lastName == null) || (lastName != null && person. lastName != null && lastName.equals(person. lastName);

   return isEqual;
}

Moving past the crazy Java code necessary to handle all the edge cases for equality between two objects, you will begin to notice all the edge cases you need to test. Here are the ones I noticed:

  • Same Object is Equal to Itself
  • Different Object Instances with Same Values are Equal to Each Other
  • If (insert property here) is null it is equal
  • If (insert property here) is null on one object but not the other it is not equal
  • If (insert property here) is not null but different than another object it is not equal

As you can see there is a minimum of 5 test cases for equals, and for each property you add, there is 3 more tests that need to be written. After copying and pasting a lot of code today, I decided to come up with a more reusable method. (Thank you Kent Beck…Red Green Refactor!)

So I came up with a little test Utility


package com.danielroop.test

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

import java.lang.reflect.Method;

public class TestUtil
{
   public static void assertPropertyEquality(Class c, String property, Object value1, Object value2) throws Exception
   {
      assertPropertyNotEqualWithDifferentValues(c, property, value1, value2);
      assertPropertyWithOneNullIsNotEqual(c, property, value1);
      assertPropertyWithOneNullIsNotEqual(c, property, value2);
      assertPropertyWithBothNullsIsEqual(c, property, value1.getClass());
      assertPropertyWithBothNullsIsEqual(c, property, value2.getClass());
   }
   
   public static void assertPropertyWithBothNullsIsEqual(Class c, String property, Class type) throws Exception
   {
      Object instance1 = c.newInstance();
      Object instance2 = c.newInstance();
      
      String propertyName = property.substring(0, 1).toUpperCase();
      propertyName += property.substring(1, property.length());
      
      Method setter = c.getDeclaredMethod("set" + propertyName, type);
      
      Object[] args = new Object[1];
      args[0] = null;
      
      setter.invoke(instance1, args);
      setter.invoke(instance2, args);
      
      assertTrue(instance1.equals(instance2));
      assertTrue(instance2.equals(instance1));
   }
   
   public static void assertPropertyWithOneNullIsNotEqual(Class c, String property, Object value) throws Exception
   {
      Object instance1 = c.newInstance();
      Object instance2 = c.newInstance();
      
      String propertyName = property.substring(0, 1).toUpperCase();
      propertyName += property.substring(1, property.length());
      
      Method setter = c.getDeclaredMethod("set" + propertyName, value.getClass());
      
      Object[] args = new Object[1];
      args[0] = null;
      
      setter.invoke(instance1, value);
      setter.invoke(instance2, args);
      
      assertFalse(instance1.equals(instance2));
      assertFalse(instance2.equals(instance1));
   }
   
   
   public static void assertPropertyNotEqualWithDifferentValues(Class c, String property, Object value1, Object value2) throws Exception
   {
      Object instance1 = c.newInstance();
      Object instance2 = c.newInstance();
      
      String propertyName = property.substring(0, 1).toUpperCase();
      propertyName += property.substring(1, property.length());
      
      Method setter = c.getDeclaredMethod("set" + propertyName, value1.getClass());
      
      setter.invoke(instance1, value1);
      setter.invoke(instance2, value2);
      
      assertFalse(instance1.equals(instance2));
      assertFalse(instance2.equals(instance1));
   }
}

It isn’t the cleanest code, but it does handle the property equality cases. So to implement this, you would just staticly import the assertPropertyEquality method (or call it using the static reference TestUtil.assertPropetyEquality). What I ended up doing in my tests, is setting aside a single method for testing property equality like so.


@Test
public void testPropertyEquality() throws Exception
{
   assertPropertyEquality(Person.class, "firstName", "Daniel", "Tyler");
   assertPropertyEquality(Person.class, "lastName", "Roop", "Hunt");
}

The first paramenter is the object that should have the property set. The secod paramenter is the java bean property that should be set. The thrid and fourth parameter are two different valid values for the property.

I am not sure if this is the best way to solve this problem, but it seemed to reduce my copy/paste code significatly.

Posted in programming, testing | Tagged , , | Leave a comment

2PP Episode 4: Bungies the Chick

The last couple weeks have been pretty busy for me. Between giving presentations, at work and at usergroups, and working on the 2nd Player Podcast. Well next week should slow down considerably and I hope to put out a few more posts about coding. One is going to be about Persistence Driven Design, which I don’t even know what that means, but I know I have an opinion. And I am currently trying to formulate my ideas about how Component Driven Design fits into how to design Flex Applications, and whether or not having a “framework” like Model-Glue Flex or PureMVC is really necessary in Flex or even makes sense.

That being said, please check out the fruits of my recent work on the latest episode of the 2nd Player Podcast.

Posted in gaming, programming | Tagged , , , | Leave a comment

JMock and AspectJ

I think it is no secret that I have become obsessed with unit testing, more specifically the mockist theory of testing. Unfortunately over the last two weeks I have come across a scenario that JMock does not allow me to test very easily.

The scenario is basically when you instantiate an object inside of a method to preform some action. This problem is only occuring because I am not using a factory to get my objects. If I were using a factory, I could inject a mock factory and all would be wonderful. Now we can debate back and forth whether I should use a factory or not, but at the end of the day it doesn’t matter, because this scenario will occur at some point. Descriptions are a lot harder than code, here is what I am talking about:


public List getPeopleHiredOn(Date hireDate)
{
   PersonSearch search = new PersonSearch();
   return search.by(hireDate);
} 

Just for good measure I will throw in a second scenario:


public void sendInvitationEmail(String address)
{
   InvitationEmail email = new InvitationEmail();
   email.sendTo(address);
   email.send();
} 

Going forward I am going to focus on the first example.

I want to point out that this situation seems to occur in the service layer of my application. The scenario is usually when I am creating a domain object to handle a request from an input to the API. However, I am sure it can occur in other places as well.

JMock gives you many options for manipulating your code, but it doesn’t do you any good unless there is a object you can inject at some point into the process. In this case, I have no such object, because the object is being created within the method I want to test. Enter AspectJ.

With AspectJ I gain the ability to intercept the creation of the PersonSearch object and replace it with a mock. My goal is to have the final test method look like this:


public class PersonServiceTest
{
...
   @Test
   public void shouldExecuteNewPersonSearchWithSuppliedDate()  
   {
      final Date hireDate = new Date();
      final List results = new ArrayList();
      PersonService service = new PersonService();
      
      mockery.checking(new Expectations(){{
         one(personSearch).by(hireDate);
         will(returnValue(results));
      }});
      
      List matchingPeople =  service.getPeopleHiredOn(hireDate);

      assertEqual(matchingPeople, results);
   }
...
}

Assuming that you have an understanding of JMock, the only thing that should look out of place would be that I never declare or initialize personSearch. This is where the magic comes in, I declare the personSearch as static and initialize it in a setup method.


public class PersonServiceTest
{
   private Mockery mockery = new Mockery() {{setImposteriser(ClassImposteriser.INSTANCE);}};
   private static PersonSearch personSearch;

   @Before
   public void resetMocks()
   {
      personSearch = mockery.mock(PersonSearch.class);
   }
...

Because I needed to extend a concrete class, I had to add the setImposteriser to the declaration of my mockery, but that isn’t really important in this example. The only unusual thing I have done is use a setup method to create my mocks instead of doing them inline and declaring them as static. I will get to the static declaration in a second.

The next step is to create our Aspect. In AOP, an Aspect is a collection of pointcuts and advise that you want to occur in your program. My Aspect looks like this:


public class PersonServiceTest
{
...

   @Aspect
   static class TestAspects
   {
      @Pointcut("call(com.danielroop.personservice.PersonSearch.new(..))")
      public void interceptPersonSearchConstructor(){}

      @Around("interceptPersonSearchConstructor()")
      public PersonSearch interceptConstructorForPersonSearch()
      {
         return personSearch;
      }
   }
}

The first thing to note, is that I used the AspectJ 5 annotation support. Next you should notice that I created this as a sub class of my test class. On a side note, I attempted making the test case an Aspect but I ran into conflicts between the JUnit and AspectJ @Before and @After annotations, because apparently AspectJ doesn’t check the type of annotation, just the name. Anyways, this is where the static personSearch is important. In order to create a subclass Aspect like I did here, you have to make it a static class, so in order to access personSearch from the parent you must make it static. I am not sure why the Aspect needs to be static, but the compiler told me so, so I didn’t argue.

That is it, at this point whenever new PersonSearch() gets called any where in this test case it will replace it with a version of my mock PersonSearch, that I can then set expectations on in my test method.

I am a little disappointed with a few of the hoops I needed to jump through, and wish that JMock incorporated Aspects into their expectations, but for now we have to make due with the tools we have.

The final class would look like this:


public class PersonServiceTest
{
   private Mockery mockery = new Mockery() {{setImposteriser(ClassImposteriser.INSTANCE);}};
   private static PersonSearch personSearch;

   @Before
   public void resetMocks()
   {
      personSearch = mockery.mock(PersonSearch.class);
   }

   @Test
   public void shouldExecuteNewPersonSearchWithSuppliedDate()  
   {
      final Date hireDate = new Date();
      final List results = new ArrayList();
      PersonService service = new PersonService();
      
      mockery.checking(new Expectations(){{
         one(personSearch).by(hireDate);
         will(returnValue(results));
      }});
      
      List matchingPeople =  service.getPeopleHiredOn(hireDate);

      assertEqual(matchingPeople, results);
   }

   @Aspect
   static class TestAspects
   {
      @Pointcut("call(com.danielroop.personservice.PersonSearch.new(..))")
      public void interceptPersonSearchConstructor(){}

      @Around("interceptPersonSearchConstructor()")
      public PersonSearch interceptConstructorForPersonSearch()
      {
         return personSearch;
      }
   }
}
Posted in testing | Tagged , , , , | 15 Comments

ROOP (programming language)

After claiming the #1 search rank in Google for daniel roop, I decided to set my eyes on a higher prize. Some people suggested I should try to claim daniel, now aside from this being a biblical character reference, it is a fairly popular name. So the odds of me being the most relevant “daniel” in the Google index seems like a stretch. However roop seems like a difficult milestone, but one that is achievable. I know at least within my Roop Family Tree, I am probably the most active on the internet, so it seems resonable, with my Buildr, participation in orlando users groups, staring a company, my personal family blog, and of course my great catalog of articles on this developer blog, that I am possibly a relevant Roop. Currently I cant’ find where this blog shows up in the Google search for Roop, but I did find something interesting.

The ROOP programming language! When I discovered this gem of a language, I immediately denounced all other languages and would only code in ROOP from hence forth. Unfortunately reality hit me, and I realized I had a hard enough time getting Ruby introduced into my work place, and I don’t think my business partner Tyler would have the same affinity to the language as I. So even though I don’t think I will be using the ROOP language to make myself any money, any time soon, I do think it was a nice find.

What I found most humorous about this find is what ROOP is used for, programming AI. She seems to believe that one day, I will program a robot that will take over the world, and destroy us all. One might ask them self, why would someone marry this person if they believed them to be capable of world destruction. I don’t know, and I try to convince her that I write business applications. I don’t think a hotel search engine, or a social rss reader, is going to take over the world because it’s intelligence is greater than a humans. But maybe she is just getting her signals crossed, maybe it isn’t me you have to worry about. Because ROOP was designed to be used for writing AI applications, like Prolog.

One day ROOP may dominate the world, but I don’t think this Roop will be that person. However maybe I can achieve #1 Google rank, which is really what life is all about.

Posted in languages, programming | Tagged , | Leave a comment

Amazon MP3

In case you haven’t heard. Amazon recently expanded it’s unboxed services to include MP3 download. The important information is tracks range in price between 0.89 – 0.99. What is cool, is the popular songs are actually cheaper. The same rules apply to the albums, popular albums are a dollar cheaper than the rest. For instance the new Kayne West album Graduation is $8.99 on Amazon MP3 and it is $9.99 on iTunes.

The other important part is the entire library is DRM free. So if you compare prices now, you are saving almost $0.50 a song if you compare a popular track on Amazon MP3 to a DRM free track on iTunes.

With all this good news, I just had to try it out and see how seemless the whole process was. First the buying experience was very similar to everything else on Amazon, that coupled with the quick download, and the automatic inclusion of the album into iTunes, I just can’t imagine a better experience. In summary the buying experience through iTunes, and Amazon are exactly the same in my opinion, one is just cheaper.

Unfortunately the Amazon catalog doesn’t seem to be quite as complete as the iTunes library. I am sure they will continue adding stuff as time passes, and competition is always good. The best thing is my iPod isn’t going to care where the music comes from, so from now I am going to search Amazon to see if they have what I am looking for, and if they don’t I will buy it on iTunes.

Posted in music | Tagged , , | 2 Comments

2PP Episode 3: It’s a Wanker!

It has been out for a few days now, but the latest episode of the 2nd Player Podcast is up and ready for your listening enjoyment. I think the content in this one was the best yet, but I am still trying to work out some of the audio issues we are having. We are currently using the i-sight mics that come with our mac book and mac book pros and the audio is being found wanting.

Anyways here it is in all of it’s video game podcast gloriousness

Posted in gaming | Tagged , | Leave a comment

JRuby vs Groovy

Lately at my office there has been some conversation about dynamic languages, and which one we should be investigating to replace dead languages like, ColdFusion, there I said it. Luckily one of the dynamic language junkies left to go work for Netscape, now Propellar, because he was a Python fan boy. I looked a little into Python and I hear tons of people probably would use Django over Rails had it been out sooner. That being said, I am glad that is one less language we need to look into before we can come to the conclusion that all of them are better than what we currently have.

So where does that leave us? Well there is myself, the Ruby/JRuby advocate, and Brian the hardcore Enterprise Java/Groovy advocate. Fortunately Groovy does not have a web presence comparable in matruity to Rails. While Grails is making great strides, from what I hear the author is still not convinced it is production ready. Brian however made a strong case for using it as it gets closer to maturity because it has been designed from the ground up to be integrated with existing J2EE standards, like JTA and JPA.

I have stated many times in this on going discussion that I am up for using whatever language we all agree to best suit our needs, and if it is Groovy I am all for it. I just don’t think our existing ColdFusion/Java/Flex combo is the most productive stack we could be using. That being said I bought into Brian’s argument, until I read the ever opinionated DHH’s recent blog post about Sun’s Craig McClanahan Keynote at RubyConf Europe. This is the guy who worked on Struts and JSF and he is advocating Rails usage. The only thing this article reminded me of was that Sun has brought the JRuby team in house, while Groovy was not invited.

To me that seems like Java is going to work a lot harder to get JRuby up to snuf with it’s standards and have the money and manpower to make that happen. You may doubt their support for JRuby but with the quick turn around on Netbeans with Ruby support, I don’t think you can question their commitment to the language.

So as much as I like what Groovy has done for the Java community and believe that there is room on the JVM for more than two languages. I think Sun is going to put their weight behind JRuby and over time will stay ahead of Groovy with support and quality of implementation of the Java Specifications. I could be completely off in this assumption, but the evidence seems to point to my observation.

Posted in development, languages | Tagged , , , , , | 5 Comments

If at first you don’t succeed…

Anyone who has been following my blog, probably knows that I have been working on some PoC work with Buildr at my office. Well when it came down to it, my boss and I decided that Buildr just isn’t quite ready for our office. After we came to the sad realization that I wouldn’t be able to use this opportunity to inject some Ruby love into my workplace, we got to talking about Ruby as a language.

Max, my boss, is very open to trying new languages and/or techniques in the office, but he does so in a much more cautious way than I would. I imagine this is because he is responsible for the entire department, while I am responsible for… just keeping my job. That being said, he told me if there was a prooof of concept that could be done to try out Ruby or in our case JRuby on Rails he would be open to the opportunity.

Well lucky for me that same day a project came across my radar, that was just that. We needed a quick site to test a potential business plan, and my initial reaction was, “hack it up in ColdFusion”. But as I told Max and Brian, while sitting on my thinking chair, I put two and two together, and got….Marvelous Ruby love. So on Thursday I pitched the idea that we use this quick and dirty project to test out JRuby in our environment. The project fits perfectly because we already told “the business” that whatever we do is just a proof of concept, so if their model works phase II of the project will have to invest time in doing it “right”. So if we find out the JRuby on Rails isn’t for us then we simply fall back to standard Coldfusion with Fusebox 5 practices and hook into whatever Java libraries we previously were using.

Let this be a lesson to all you Ruby hopefuls out there. At some point your boss will give into a PoC in hopes that you will fail misserably and stop talking about it because you are too embarrassed to bring it up anymore, so you can proove to him that Ruby is a much better language than ColdFusion.

Posted in development | Tagged , , , , | 4 Comments

Google Search Results

Last night was an amazing suprise for me. As I finally achieved something I have been struggling with for some time now. Getting ranked #1 when you search for daniel roop. You wouldn’t think this would be a problem, unless of course there is a poet who happens to have the same name as you. Well poet, I win for now, and I took a screen shot to remember it forever.

Posted in community, Life | Tagged | 4 Comments

2nd Player Video Game Podcast Episode 2

The second episode of the critically acclaimed video game podcast, 2nd Player, was just released last night. Go check it out and tell us what you think.

Posted in gaming | Tagged | Leave a comment