BrownBeast
BrownBeast

Reputation: 21

Unit Testing with modifying static variables during initialization

I have a class that has static variables assigned during initialization. I would like to write unit tests for this class with modifying values for this static variable. Below is a simple code to explain my scenario

Class to test:

public class Hello {
private final static String HELLO_FINAL = "Hello " + HelloTo.getInstance().getHelloTo(); // I would like to modify this value between tests

  public String sayHello() {
    return HELLO_FINAL;
  }
}

Supporting class:

public class HelloTo {
  private String helloTo = "World";
  private static HelloTo singleton = new HelloTo(); 
  private HelloTo() {}  
  public static HelloTo getInstance() {
    return singleton;
  }
  public void setHelloTo(String helloTo) {
    this.helloTo = helloTo;
  }
  public String getHelloTo() {
    return helloTo;
  }
}

Test class:

import org.junit.Assert;
import org.junit.Test;
public class HelloTest {
  @Test
  public void testDefault() {
    Assert.assertEquals("Hello World", new Hello().sayHello());
  }
  @Test
  public void testDynamic() {
    HelloTo.getInstance().setHelloTo("My name");
    Assert.assertEquals("Hello My name", new Hello().sayHello());
  }
}

Is there a way to make both tests successful. Currently I get a failure for testDymanic() saying:

org.junit.ComparisonFailure: expected:<Hello [World]> but was:<Hello [My name]>

Thanks in advance!

Upvotes: 0

Views: 2578

Answers (2)

shmosel
shmosel

Reputation: 50716

HELLO_FINAL is only initialized once per run; you can't reinitialize it within the same JVM. Is there a way to make both tests successful? Sure, there are countless ways. But that depends on what you're trying to test, which is not completely clear from your example.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533530

Using a mutable singleton in a tests is an known problem. You have to reset the state of the singleton between tests, of even better, don't use a singleton in your tests.

You could do something like:

public enum HelloTo {
  INSTANCE;
  private String helloTo = "World";
  public void reset() {
    setHelloTo("World");
  }
  public void setHelloTo(String helloTo) {
    this.helloTo = helloTo;
  }
  public String getHelloTo() {
    return helloTo;
  }
}

public class Hello {
  public static String sayHello() {
    // has to be dynamic as helloTo can change.
    return "Hello " + HelloTo.INSTANCE.getHelloTo(); 
  }
}

public class HelloTest {
  @Before
  public void setUp() {
    HelloTo.INSTANCE.reset();
  }
  @Test
  public void testDefault() {
    Assert.assertEquals("Hello World", Hello.sayHello());
  }
  @Test
  public void testDynamic() {
    HelloTo.INSTANCE.setHelloTo("My name");
    Assert.assertEquals("Hello My name", Hello.sayHello());
  }
}

Upvotes: 2

Related Questions