Test singleton with jUnit

我的未来我决定 提交于 2019-12-21 21:04:32

问题


I have a factory class to retrieve the configuration for my application:

public class ConfigurationFactory {
private static ConfigurationFactory configurationFactory = new ConfigurationFactory();

private Configuration configuration = null;

public static ConfigurationFactory getConfigurationFactory() {
        return configurationFactory;
    }

And some getConfiguration methods depending on where I am getting the config from (file, database, default, etc...):

public Configuration getConfiguration(String path){...}
public Configuration getConfiguration(String database){...}

My problem is that when I do unit test for each method, I have to restart the singleton in order to load from a different source, so the only thing I had come up to is adding this:

public void resetConfiguration() {
 this.configuration = null;
}

And I feel I'll burn in developer's hell for doing it :)

My question: Is there any other way to do it without adding this method?

Note: I have seen this and I cannot use any DI framework like Spring or Guice, management thinks adding a framework would make the project heavyweight, as this program is intended to run as a daemon on servers.


回答1:


Some of the things which i can think of are

  1. Use mocking frameworks like Easymock or Mockito to mock the ConfigurationFactory and use this mock objects in other calling areas.

  2. Have a setter defined in the ConfigurationFactory class and define an annotation like @TestPurpose and use this to override the singleton object from your unit tests. The annotation is to denote that this should not be used during the application flow and the function is meant only for junit purpose.




回答2:


The first thing to fix is that your singleton should not be static. Here are a couple of articles showing you how to do that:

  • Rehabilitating the singleton pattern.
  • Dependency injection.

Once you have fixed this, you will no longer need to reset your singletons since you'll be able to inject them at will.




回答3:


If you don't want to use suggested frameworks you can still just split 'src 'and 'test-src' and use a protected method instead of a public one. Thats not ideal but prevents calls of that reset-method while enabling you to test.

  • src/main/myproject.myfactory.ConfigurationFactory
  • src/test/myproject.myfactory.TestConfigurationFactory

-> in your JUnit-class use the @After or @AfterClass -methods to call reset

If you need the Factory throughout multiple test Scenarios you can also make an abstract BaseTest-class which contains an @AfterClass method to clean such Singletons.

Also you could enforce the reset by reflection in your test-code and use no extra reset-method at all but i would not recommend that.




回答4:


You can use reflection, for example

public void resetSingleton() throws Exception {
   Field instance = FormatterService.class.getDeclaredField("instance");
   instance.setAccessible(true);
   instance.set(null, null);
}

See an example



来源:https://stackoverflow.com/questions/10510894/test-singleton-with-junit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!