Assuming your class is something like:
class ClassToTest {
public void doSomething() {
String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
// Do something with sessionId
}
}
If you don't have the ability to change the class that uses RequestContextHolder
, then you could override the RequestContextHolder
class in your test code.
I.e. you create a class with the same name, in the same package, and ensure it is loaded before the actual Spring class.
package org.springframework.web.context.request;
public class RequestContextHolder {
static RequestAttributes currentRequestAttributes() {
return new MyRequestAttributes();
}
static class MyRequestAttributes implements RequestAttributes {
public String getSessionId() {
return "stub session id";
}
// Stub out the other methods.
}
}
Now, when your tests run, they will pick up your RequestContextHolder
class and use that in preference to the Spring one (assuming the classpath is set up for this to happen).
This isn't a particular nice way of getting your tests to run, but it might be necessary if you can't change the class you are testing.
Alternatively, you could hide the session id retrieval behind an abstraction. For example introduce an interface:
public interface SessionIdAccessor {
public String getSessionId();
}
Create an implementation:
public class RequestContextHolderSessionIdAccessor implements SessionIdAccessor {
public String getSessionId() {
return RequestContextHolder.currentRequestAttributes().getSessionId();
}
}
And use the abstraction in your class:
class ClassToTest {
SessionIdAccessor sessionIdAccessor;
public ClassToTest(SessionIdAccessor sessionIdAccessor) {
this.sessionIdAccessor = sessionIdAccessor;
}
public void doSomething() {
String sessionId = sessionIdAccessor.getSessionId();
// Do something with sessionId
}
}
Then you can provide a dummy implementation for your tests:
public class DummySessionIdAccessor implements SessionIdAccessor {
public String getSessionId() {
return "dummy session id";
}
}
This sort of thing highlights a usual best-practice to hide certain environmental details behind abstractions so that you can swap them out if your environment changes.
This applies equally to making your tests less brittle by swapping dummy implementations for 'real' ones.