简体   繁体   中英

How to handle session variables in unit tests

I'd like to know how do I handle session variables in my unit tests.

For example, I have the variable user logged in which is loaded by the session, but the session does not exist at the time of running the tests.

How do I handle these cases without changing the code of the tested class ? I'm using Junit.

Thanks everyone, Jean

how do I handle session variables in my unit tests

Short answer: You don't. Unit tests run in isolation and must not be coupled to the infrastructure.


Further explanation...

Ideally you should try not to use session at all. Stateless applications are much easier to test, maintain, scale, etc. Of course, sometimes you have to track some measure of state. But don't use session as a catch-all place to manage that state. You might track different elements of state in different places, such as cookies or page values or a database.

If you must use session, abstract it behind an interface. Create some kind of interface for providing state management and implement that interface using session. The application would use that implementation, the unit tests would mock that implementation. This de-couples the logic of the application (which you want to test) from the management of state (which you can test separately as an integration test).

An extremely simple example of such an interface could be something like:

public interface StateValueManager {
    String getValue(String key);
    void setValue(String key, String value);
}

Internal to the implementation you would be storing values in session state. You might later use another implementation which stores values in a database instead. The point is to de-couple it from the rest of the code so you can change state management technology any time you like (including using a mock for testing).

As you progress further, you might replace these simple get/set value methods with more directed methods, such as storing a (potentially serializable) "state object" which contains some business logic about that state, or perhaps creating separate methods for storing specific kinds of business state instead of just raw values. The sky's the limit, really.

Once you've de-coupled this, any object in your application would then need to require an implementation. Perhaps something like this:

public class SomeObject {
    private final StateValueManager state;

    public SomeObject(StateValueManager state) {
        this.state = state;
    }
}

Now that object can get/set values in state (session state specifically, but SomeObject doesn't really care about that) as long as the code calling that object provides it with a state manager implementation. Your unit tests would supply it with a mock instead.

Use a Mocking-Framework to mock the session.

Mockito: http://code.google.com/p/mockito/

public class TestClass {

  @Mock
  private HttpSession session;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
  }

  @Test    
  public void testMethod() {
    Mockito.doReturn("ok").when(session).getAttribute("abc");
    ...
    classToTest.doIt(session);
  } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM