我有一个方法可以播放Http.Context
和"做一些事情"随着会议。我想为这个方法编写一个单元测试。具体来说,我想测试一下,如果请求带有某些标头我的方法正常工作。似乎最可靠的方法是为我的测试创建FakeApplication
和Controller
。然后,我使用Helpers.fakeRequest
来获取请求,并Helpers.route
将该请求路由到我的控制器。控制器会调用我的方法,设置一些变量等等,然后我可以断言成功等等。
似乎是一个精彩的计划,但我无法弄清楚如何在FakeApplication
中向我的控制器添加路线。请注意,此控制器并非真正属于我的应用程序 - 它只是我想要用于此一项测试的内容。所以我想定义它并在这个单元测试中构建;我不想将其添加到我的conf/routes
文件中。
具体来说,我想要这样的事情:
// Maybe I can use GlobalSettings.onRouteRequest but the return type
// is play.api.mvc.Handler which seems inaccessible from Java
FakeApplication app = Helpers.fakeApplication(new MyGlobalSettings());
Http.Request request = Helpers.fakeRequest().withCookies(...).withBody(...);
Controller testContoller = new MyTestController();
// This doesn't exist, but I want something like this
app.addRoute("/foo", ctx -> testController.method(ctx));
running(app, () -> {
Helpers.route("/foo");
assertThat(testContoller.itWorked()).isTrue();
}
我正在运行Play 2.2.3并使用Java编写,而不是Scala。
我意识到我可以直接构造Http.Context
并将其传递给我的方法。但是,出于以下几个原因,这不是我的首选方法:
Http.Context
构造函数采用会话变量的纯文本。我希望在请求包含加密会话cookie时测试一些正常工作。Http.Context
构造函数记录很少,看起来有些偏差。例如,您可以将Http.Request
传递给构造函数,但也可以传递cookie数据和会话数据。那么请求中的cookie /会话数据会发生什么?它是否与传递的其他数据合并?忽略?Http.Context
构造函数很难从Java中使用,因为它需要play.api.mvc.RequestHeader
,它不能用Java构建,而play.mvc.Http.Request
也不能用FakeRequest
有用的""由Java构建(您可以构建一个,但不包含cookie,标题等,Http.Request
无法转换为Http.Context
。return MyStuffObjs.Select(item => (MyStuff)item.Clone()).ToArray();
(例如,手动构建上下文似乎更有可能打破新版本的游戏)。 / LI>
有什么想法吗?
答案 0 :(得分:1)
以格式播放测试
running(fakeApplication(), () -> {
...
});
适用于在没有HTTP层的情况下测试正在运行的播放应用。但是在你的情况下,你依赖于一个http上下文,所以我可以选择添加http层......
running(testServer(3333), fakeApplication(), () -> {
WSResponse wsResponse = WS.url("http://localhost:3333/foo").setHeader("fizz", "buzz").get().get(30, TimeUnit.SECONDS);
....
//assert some stuff
});
或者尝试使用PowerMockito并模拟HTTP.Context调用。正如你所指出的那样,这更加脆弱,但可以实用地进行快速单元测试。像
这样的东西@RunWith(PowerMockRunner.class)
public class FooTest {
@PrepareForTest({ Http.Context.class })
@Test
public void test() {
mockStatic(Http.Context.class)
mockStatic(Http.class)
Http.Context mockContext = mock(Http.Context.class);
Map<String, String> args new HashMap<>();
args.put("a","b");
mockContext.args = args;
PowerMockito.when(Http.Context.current()).thenReturn(mockContext);
ClassUnderTest cut = new ClassUnderTest();
cut.someMethod();
//assertions
}
}
答案 1 :(得分:0)
@Before
public void startPlay() {
String conf = System.getProperty("config.file");
if (conf == null) {
System.setProperty("config.file", "../../conf/test.conf");
}
System.setProperty("play.http.router", "customer.Routes");
super.startPlay();
}
答案 2 :(得分:-1)
这是您在不更改conf/routes
文件的情况下添加其他测试路线的方法。但MyTestController.java需要位于project / app而不是project / test。
// app/controllers/TestController.java
public static Result foo() {
return ok();
}
// conf/test.routes
GET /foo controllers.TestController.foo
// test/controllers/TestTestController.java
@Before
Configuration config = new Configuration(ConfigFactory.parseFile(new File("conf/test.conf")).resolve());
Map<String, Object> configMap = config.asMap();
Map<String, Object> application = (Map<String, Object>) config.get("application");
application.put("router", "test.Routes");
configMap.put("application", application);
fakeApplication(configMap);
@Test
FakeRequest fakeRequest = Helpers.fakeRequest("GET", "/foo");
Result result = Helpers.route(fakeRequest);
assertThat(Helpers.status(result)).isEqualTo(200);