0

I'm trying to unit test some code utilizing Hazelcast. Most of the code is straightforward, but I've been having hangups with the class constructor.

private final static Logger LOGGER = Logger.getLogger(ClientViewer.class);
protected static HazelcastInstance client;

public ClientViewer() {
    setup();
}

private void setup() {
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.getGroupConfig.setName(System.getProperty("hazelcast.group")).setPassword(System.getProperty("hazelcast.password"));
    clientConfig.getNetworkConfig().addAddress(System.getProperty("hazelcast.url"));
    client= HazelcastClient.newHazelcastClient(clientConfig);
}

So any time I try to create a test object to call/test its methods, it keeps throwing an IllegalArgumentException. So I decided to set each property individually before creating the test object using test data.

TEST_GROUP = "testGroup";
TEST_PASSWORD = "testPassword";
TEST_URL = "testUrl";

System.setProperty("hazelcast.group", TEST_GROUP);
System.setProperty("hazelcast.password", TEST_PASSWORD);
System.setProperty("hazelcast.url", TEST_URL);

But now I'm getting an InvocationTargetException. What am I missing? Is there a way to fool the setup method without dependency injection?

(BTW: I'm aware dependency injection is kind of an obvious good practice, but that idea is somewhat lost among my peers. Suffice to say, that's not an option in this scenario.)

Miles Peterson
  • 265
  • 1
  • 4
  • 12
  • Dependcy injection might or might not be a good idea, but why are you reading the System properties directly inside your class? You could use a `setProperties(Map)` method, then your live code could insert the system properties and your testcode could use others. In any case, posting the exception would have been a good idea... – Florian Schaetz Aug 04 '15 at 16:13
  • InvalidArgumentException if I remember correctly. I've made various tweaks since then. I wanted to see if I could somehow mock HazelcastClient using the any() method, but so far no luck. Now it's complaining about value for key log4j.appender.stdout. I'll edit the code accordingly. – Miles Peterson Aug 04 '15 at 16:23
  • Without the current, exact error message, your chances of finding someone who can help you are drastically reduced, I'm afraid. – Florian Schaetz Aug 04 '15 at 16:40
  • java.lang.IllegalArgumentException: argument 'group name' cant be null – Miles Peterson Aug 04 '15 at 16:51
  • That's why I set the system properties. When that happens, I get an IllegalStateException on account of not being able to connect to a live Hazelcast instance. Even if I could connect, my code would become an integration test, which defeats the purpose of a unit test. So right now I'm trying to somehow fool HazelcastClient.newHazelcastClient(clientConfig) into running without throwing an error of some kind. – Miles Peterson Aug 04 '15 at 16:55
  • 1
    why don't you refactor your code so that all the parameters are provided as arguments and a further method just invokes this method and reads all the properties and passes it to the method. This simplifies testing quite a bit as you can provide these methods easily at test time. I don't think you want to run an integration test where you test if getting values from `System.getProperties(...)` really works? You can also try to [mock `System.getProperty(...)`](http://stackoverflow.com/questions/20404276/mock-system-class-to-get-system-properties) – Roman Vottner Aug 04 '15 at 16:55
  • Bingo. The trick here is to refactor the whole thing, allowing you to mock a Hazelcast instance, for example. – Florian Schaetz Aug 04 '15 at 16:56
  • Isn't testing the functionality of a Hazelcast client per se an integration test?! – Roman Vottner Aug 04 '15 at 16:56
  • If by refactor you mean rewrite the code, then I'm afraid that's not an option. I've been told this code has to be unit tested as is, and I'll be the first to admit how asinine this method is. – Miles Peterson Aug 04 '15 at 17:04
  • 1
    I've a couple of problems regarding the presented code and unit-testing. Testing `System.getProperty(...)` is done already by the JVM vendor of your choice (hopefully). Also, testing the initialization of a Hazelcast client is done by Hazelcast already. Testing the constructor does not return anything - therefore you need whitebox-testing. Mocking all of the external classes also is useless in my opinion as what is really tested then? Creating a real Hazelcast client with the provided properties is already an integration test! – Roman Vottner Aug 04 '15 at 17:19
  • I'm not trying to test ClientViewer's setup() method. The problem is that the ClientViewer object I'm using in my unit tests has the setup() method in its constructor, and therefore calls the setup() method when it's instantiated. The whole point of the exercise is to somehow bypass the setup() method so that it won't throw an error when I try to unit test the other class's methods. – Miles Peterson Aug 04 '15 at 17:25

1 Answers1

0

Let me put this to rest once and for all. I just found aout about something in PowerMock called Whitebox that suppresses a class's constructor.

final ClientViewer testObject = newInstance(ClientViewer.class);
testObject.client = mockHazelcastInstance;

By placing the above code in your test method, we completel bypasses that pesky setup() method and substitute the class's client property with a mocked one. That will allow us to verify the client's behavior without the need to initialize a Hazelcast instance.

This took me the better part of three days to figure out. I only found this out in the last five minutes. I apologize for any trouble or confusion I might have caused, and I am certainly grateful for all of your help. Thank you.

Miles Peterson
  • 265
  • 1
  • 4
  • 12