简体   繁体   English

如何在单元测试中处理会话变量

[英]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. 例如,我登录了变量user,该变量由会话加载,但是在运行测试时该会话不存在。

How do I handle these cases without changing the code of the tested class ? 我如何在不更改测试类代码的情况下处理这些情况? I'm using Junit. 我正在使用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. 您可能在不同的位置跟踪不同的状态元素,例如cookie或页面值或数据库。

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. 现在,只要调用该对象的代码为该对象提供状态管理器实现,该对象就可以在状态(特别是会话状态,但SomeObject并不关心)中获取/设置值。 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/ 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);
  } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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