title: JUnit Mock Singleton Class with Environment Variables
body: <p>I have a singleton Class as follows: </p>
  
  <pre><code> public class PropertiesSingleton {
  private static PropertiesSingleton instance;
  
  private static ApplicationContext ctx = new 
  AnnotationConfigApplicationContext(PropertiesConfig.class);
  
  public static PropertiesSingleton getInstance(){
      if(instance == null){
          synchronized (PropertiesSingleton.class) {
              if(instance == null){
                  instance = new PropertiesSingleton();
              }
          }
      }
      return instance;
  }
  
  public Environment env(){
      return ctx.getEnvironment();
  }
  }
  </code></pre>
  
  <p>The PropertiesConfig Class as follows: </p>
  
  <pre><code>@Configuration
  @ComponentScan("someComponent")
  @PropertySources({@PropertySource("file:${someName}/foo/foo.properties"),
  @PropertySource("classPath:Properties")
  })
  public class PropertiesConfig {
  @Autowired
  private Environment env;
  }
  </code></pre>
  
  <p>And it is being called in Controller as Follows: </p>
  
  <pre><code>@CrossOrigin
  @RestController
  @RequestMapping(value="/mappingUrl")
  public class MappingController{ 
  static Environment env = PropertiesSingleton.getInstance().env();
  }
  </code></pre>
  
  <p>What I am trying to do is get the mocked value for env in controller and I am trying it following way: </p>
  
  <pre><code>@Before
  public void setUp() throws Exception {
       MockEnvironment env = new MockEnvironment();
       env.setProperty("serverName", "test");
  
       PropertiesSingleton environmentMock = 
       PowerMockito.mock(PropertiesSingleton.class);
       Whitebox.setInternalState( PropertiesSingleton.class, "INSTANCE", 
       environmentMock );
       when(environmentMock.getInstance().env())
          .thenReturn(env);        
       }
  </code></pre>
  
  <p>But I get following errors: </p>
  
  <p>SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
  SLF4J: Defaulting to no-operation (NOP) logger implementation
  SLF4J: See <a href="http://www.slf4j.org/codes.html#StaticLoggerBinder" rel="nofollow noreferrer">http://www.slf4j.org/codes.html#StaticLoggerBinder</a> for further details.</p>
  
  <p>and looking at stack trace I see following: </p>
  
  <p>org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [propertiesConfig.class]</p>
  
  <p>org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.</p>
  
  <p>Any help is appreciated......</p>
  
  <p>EDIT:</p>
  
  <p>Here is my full test method--</p>
  
  <pre><code>import javax.servlet.http.HttpServletRequest;
  import org.junit.jupiter.api.Test;
  import org.junit.runner.RunWith;
  import org.mockito.InjectMocks;
  import org.mockito.Mock;
  import org.mockito.Spy;
  import org.powermock.modules.junit4.PowerMockRunner;
   import org.springframework.test.context.TestPropertySource;
  import org.springframework.test.web.servlet.MockMvc;
  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  import org.apache.log4j.Appender;
  import org.apache.log4j.Level;
  import org.junit.Before;
  import org.apache.log4j.Logger;
  import static org.mockito.Mockito.*;
  import static 
  org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
  import static 
  org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  
  import java.nio.charset.Charset;
  import org.springframework.core.env.Environment;
  import org.springframework.http.MediaType;
  import org.powermock.api.mockito.PowerMockito;
  import org.powermock.core.classloader.annotations.PrepareForTest;
  @RunWith(PowerMockRunner.class)
  @PrepareForTest(PropertiesSingleton.class)
  @TestPropertySource(locations="classpath:someclassPath")
  public class MappingControllerTest{
  
  private MockMvc mockMvc;
  
  JSONObject  obj = new JSONObject("{" 
          + "\"_id\": \"184DZ01C\"," 
          + "\"text\": \"textTest\","                  
          + "\"image\" : \"Test.png\"," 
          + "\"link\" : \"www.testFile.com\"," 
          + "\"title\" : \"testTitle\"," 
          + "\"weight\" : \"0\","
          + "}");
  
  public static final MediaType APPLICATION_JSON_UTF8 = new 
  MediaType(MediaType.APPLICATION_JSON.getType(), 
  MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
  
  
  @InjectMocks
  @Spy
   MappingController _mappingController = new MappingController();
  
  
  
  @Mock
  private Appender logAppender;  
  
  
  
  @Mock
  private Environment environmentMock;
  
  
  @Mock
  private PropertiesSingleton singletonMock;
  
  
  
  
   @Before
      public void setUp() throws Exception {
       Logger logger = Logger.getLogger(ReviewWfEndpoint.class);
       logger.addAppender(logAppender);
       logger.setLevel(Level.INFO);
  
      }
  
  
  
  
   @Test
   public void TestReviewWfEndpoint_pass()
    throws Exception {    
      String expectedServer = "test";
      String expectedServerPropertyName = "serverName";
  
      PowerMockito.mockStatic(PropertiesSingleton.class);
      when(PropertiesSingleton.getInstance()).thenReturn(singletonMock);
      when(singletonMock.env()).thenReturn(environmentMock);
      when(environmentMock.getProperty(expectedServerPropertyName))
      .thenReturn(expectedServer);
      this.mockMvc.perform(post("/mappingUrl/map")
              .contentType(APPLICATION_JSON_UTF8)
              .content(jString)
              .accept(MediaType.APPLICATION_JSON))                
              .andExpect(status().isOk());
  
  }
  
  }
  </code></pre>
  
  <p>and in my controller I use env like this: </p>
  
  <pre><code>@CrossOrigin
  @RestController
  @RequestMapping(value="/mappingUrl")
  public class MappingController{ 
  static Environment env = PropertiesSingleton.getInstance().env();
  @RequestMapping(value="/map", method=RequestMethod.POST, 
  produces="application/json")
  public ResponseEntity&lt;Object&gt; map(@RequestBody String jsonString){
  String environmentName = 
  env.getProperty("Constant");
  }
  }
  </code></pre>