我在Java单元测试非常新,我听说框架的Mockito是用于测试目的真的很好。
我公司开发的REST服务器(CRUD方法),现在我要测试,但我不知道怎么样?
更不知该测试程序应该如何开始。 我的服务器应该在localhost工作,然后对这个URL调用(如本地主机:8888)?
以下是我试过到目前为止,但我敢肯定,这是不正确的做法。
@Test
public void testInitialize() {
RESTfulGeneric rest = mock(RESTfulGeneric.class);
ResponseBuilder builder = Response.status(Response.Status.OK);
builder = Response.status(Response.Status.OK).entity(
"Your schema was succesfully created!");
when(rest.initialize(DatabaseSchema)).thenReturn(builder.build());
String result = rest.initialize(DatabaseSchema).getEntity().toString();
System.out.println("Here: " + result);
assertEquals("Your schema was succesfully created!", result);
}
下面是代码initialize
方法。
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/initialize")
public Response initialize(String DatabaseSchema) {
/** Set the LogLevel to Info, severe, warning and info will be written */
LOGGER.setLevel(Level.INFO);
ResponseBuilder builder = Response.status(Response.Status.OK);
LOGGER.info("POST/initialize - Initialize the " + user.getUserEmail()
+ " namespace with a database schema.");
/** Get a handle on the datastore itself */
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
datastore.put(dbSchema);
builder = Response.status(Response.Status.OK).entity(
"Your schema was succesfully created!");
/** Send response */
return builder.build();
}
在这个测试用例我想一个JSON字符串发送到服务器(POST)。 如果一切顺利,则服务器应该以“你的模式是创建成功!”回复。
有人可以帮帮我吗?
好。 因此,该方法的合同如下:解析输入字符串作为JSON,并发送回BAD_REQUEST
如果它是无效的。 如果它是有效的,建立在实体datastore
与各种属性(你认识他们),并发送回OK
。
而你需要验证,该合同是由方法来实现。
哪里帮助的Mockito这里? 好吧,如果你没有测试此的Mockito的方法,你需要一个真正的DataStoreService
,你需要验证实体已经在这个真正的正确创建DataStoreService
。 这是你的测试是不是一个单元测试了,这也是它太复杂了测试,太长,太难以运行,因为它需要一个复杂的环境。
可以的Mockito通过嘲讽的依赖帮助DataStoreService
:您可以创建一个模拟DataStoreService
,并确认这个模拟确实与适当的实体参数调用,当你打电话给你initialize()
方法,在您的测试。
要做到这一点,你需要能够将注入DataStoreService
到您的被测物。 它可以在下面的方式重构你的对象一样容易:
public class MyRestService {
private DataStoreService dataStoreService;
// constructor used on the server
public MyRestService() {
this.dataStoreService = DatastoreServiceFactory.getDatastoreService();
}
// constructor used by the unit tests
public MyRestService(DataStoreService dataStoreService) {
this.dataStoreService = dataStoreService;
}
public Response initialize(String DatabaseSchema) {
...
// use this.dataStoreService instead of datastore
}
}
现在,在您的测试方法,你可以这样做:
@Test
public void testInitializeWithGoodInput() {
DataStoreService mockDataStoreService = mock(DataStoreService.class);
MyRestService service = new MyRestService(mockDataStoreService);
String goodInput = "...";
Response response = service.initialize(goodInput);
assertEquals(Response.Status.OK, response.getStatus());
ArgumentCaptor<Entity> argument = ArgumentCaptor.forClass(Entity.class);
verify(mock).put(argument.capture());
assertEquals("the correct kind", argument.getValue().getKind());
// ... other assertions
}
什么你在谈论听起来更像集成测试不会有太大的使用你的和的Mockito(或任何其他嘲讽框架)。
如果你想你写单元测试代码,肯定的Mockito是一个有用的工具。
我建议你阅读更多关于嘲讽/单元测试和它应该被使用的情况。
的Mockito(通常)用于测试的代码部分 ; 例如,如果你在你的消费REST服务,但不想做一个全栈测试,你会嘲笑那个连接到REST服务,让您精确,和一致,测试特定问题的服务。
为了测试REST服务(例如,特定服务方法)的内部部分没有碰到一个数据库,你会嘲笑DB子系统,只允许内部服务测试,不涉及DB。 该试验属于REST服务模块,而不是客户端凹进去了。
为了测试REST服务本身你使用真正的客户端库,创建一个全栈集成测试。 可能的Mockito这里用来嘲笑客户无关的REST服务消费的部分。
最好的方法是使用wiremock添加下面的依赖com.github.tomakehurst wiremock 2.4.1 org.igniterealtime.smack嫌核心4.0.6
定义和使用wiremock如下所示
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
String response ="Hello world";
StubMapping responseValid = stubFor(get(urlEqualTo(url)).withHeader("Content-Type", equalTo("application/json"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json").withBody(response)));
我同意这是不是单元测试,但集成测试,反正你宁愿看看球衣和嵌入式灰熊服务器测试。 为了萨姆起来,这个代码启动灰熊服务器在本地主机(可以启动datbase以及):8888,然后安装客户端的球衣的客户端和sents POST请求,响应应该进行测试。 这是一个整合,因为你同时测试服务器和数据库,你可以使用但是的Mockito来模拟数据库,但要看怎么绑你的服务器和数据库。
(使用的球衣1.11和篦条筛2.2试验)
@BeforeClass
public static void setUpClass() throws Exception {
// starts grizzly
Starter.start_grizzly(true);
Thread.sleep(4000);
}
@Before
public void setUp() throws Exception {
client = new Client();
webResource = client.resource("http://localhost:8888");
}
@Test
public void testPostSchemaDatabase() throws Exception {
{
String DatabaseSchema = "{ database_schema : {...}}";
logger.info("REST client configured to send: " + DatabaseSchema);
ClientResponse response =
webResource
.path("/initialize")
.type("application/json")
.post(ClientResponse.class, DatabaseSchema);
//wait for the server to process
Thread.sleep(2000);
assertEquals(response.getStatus(), 204);
//test the response
}
}
@After
public void after() throws JSONException
{
//probably you want to delete the schema at database and stop the server
}