0

My application has this structure: there's a RepositoryFacade (that is a Singleton) that uses many other ObjectRepository that are Singleton (UserRepository, etc).

Now I'd like to test it, mocking the [Objetct]Repositiries. To do that I made the [Objetct]Repositiry implements an interface, and then i tried to:

final IUserRepository mockIUserRepository= context.mock(IUserRepository.class);
RepositoryFacade.getInstance().setUserRepository(mockIUserRepository);
final User testUser = new User("username");

// expectations
context.checking(new Expectations() {{
    oneOf (mockIUserRepository).save(testUser);
}});
// execute
RepositoryFacade.getInstance().save(testUser);

And in RepositoryFacade I added:

public IUserRepository userRepository = UserRepository.getInstance();

But if I try to run the test, I obtain:

java.lang.SecurityException: class "org.hamcrest.TypeSafeMatcher"'s signer 
information does not match signer information of other classes in the same 
package

p.s. Originally my RepositoryFacade had not a IUserRepository variable, I used it asking always UserRepository.getInstance().what_i_want(). I introduced it to try to use JMock, so if not needed I'll be glad to remove that bad use of Singleton.

Thanks, Andrea

andreaxi
  • 931
  • 5
  • 15
  • 28
  • 2
    Congratulations, you've discovered one of the reasons why singletons are a horrible idea. :) My best advice: [get rid of them](http://jalf.dk/singleton/) – jalf Aug 12 '12 at 11:09

1 Answers1

2

The error you're getting suggests that you have a classloading issue with the org.hamcrest package rather than any issue with your singletons. See this question for more on this exception and this one for the particular problem with hamcrest and potential solutions.

Check your classpath to make sure you're not including conflicting hamcrest code from multiple jars. If you find hamcrest in multiple jars, this may be corrected by something as simple as changing their order in your classpath.

Junit itself comes in two versions - one may include an old version of hamcrest. Switching to the one not including hamcrest may also fix your problem.

If you can find a way to do it, it would be better in the long run to get rid of the singletons altogether and instead do dependency injection using something like Spring or Guice.

But what you're doing should work, once you deal with the classloading, and it's a reasonable approach to dealing with singletons in a testing context.

Community
  • 1
  • 1
Don Roby
  • 40,677
  • 6
  • 91
  • 113
  • First of all, thanks. In my classpath there are: hamcrest-core-1.1.jar, hamcrest-library-1.1.jar, jmock-2.5.1.jar, jmock-junit4-2.5.1.jar. So, do you think it's a "conflict" between the first two? I'm trying to change the order, or something similar. Let you know, thanks – andreaxi Aug 12 '12 at 12:19
  • Nothing changes, but probably this is the key: "Use junit-dep.jar rather than junit.jar- this is JUnit minus it's dependencies. Junit.jar contains an old version of Hamcrest." (src: your second link). I'm going to try. – andreaxi Aug 12 '12 at 12:26
  • Ok, fixed. But I had to do an awful trick: since I use it from Eclipse, I automatically added JUnit4 and it contains "org.hamcrest.core_1.1.0.v20090501071000.jar". So, I tryed to move it away from the Build Path panel, but it was not possible. Then I tried "deleteting it" (read "move it away"), but it caused an error because (obviously) it didn't find it and it was impossible to remove from build path. So I renamed my "hamcrest-library-1.1.jar" in "org.hamcrest.core_1.1.0.v20090501071000.jar" and it worked. Bad behaviour, but it works. Do you know better ways to do that? Thanks for your help! – andreaxi Aug 12 '12 at 12:35
  • The issue of dealing with the classpath in eclipse might be worthy of a new question. One thing I would look into is using maven, but others might have better or more complete answers. – Don Roby Aug 12 '12 at 12:47