1

我用四种方法创建了一个 Rest 服务,GET、POST、UPDATE 和 DELETE。这些方法与数据库建立连接以检索和存储数据。

现在我想测试每种方法。我为此使用了 Jersey 测试框架。只要我删除实际调用数据库的代码,它就可以工作。当我离开调用数据库的代码时,它会引发无法连接到数据库的异常。

编辑:我做了一些研究并使用了依赖注入。db 调用被移到一个单独的类,但我仍然做错了什么。

数据库结果。在这个类中调用数据库。

public class DatabaseResults {

private final String getQuery = "SELECT * FROM movies";
private Connection connection = null;
private PreparedStatement pstmt = null;
private final ArrayList<Movie> jsonList = new ArrayList<>();

public JSONObject getAllMovies() throws SQLException {

    try {
        ComboPooledDataSource dataSource = DatabaseUtility.getDataSource();
        connection = dataSource.getConnection();

        pstmt = connection.prepareStatement(getQuery);
        ResultSet rs = pstmt.executeQuery();

        while (rs.next()) {
            jsonList.add(new Movie(rs.getString(1), rs.getString(2), rs.getString(4), rs.getString(3)));
        }

    } catch (SQLException ex) {
        System.out.println(ex);
        System.out.println("Could not retrieve a connection");
        connection.rollback();
    } finally {
        connection.close();
    }

    JSONObject jsonObject = new JSONObject();
    jsonObject.put("movies", jsonList);

    return jsonObject;
    }
}

包含 REST 方法的 MoviesResource

@Path("movies")
public class MoviesResource {

....
private DatabaseResults dbResults = null;

public MoviesResource() {
    this(new DatabaseResults());
}

MoviesResource(DatabaseResults dbr){
     this.dbResults = dbr;

}
....
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllMovies() throws JSONException, SQLException {

    return Response.status(200).entity(dbResults.getAllMovies().toString()).build();
}

测试类

@RunWith(MockitoJUnit44Runner.class)
public class MovieResourceTest extends JerseyTest {

JSONObject jsonObject = new JSONObject();

@Mock
DatabaseResults dbr;  

@Before
public void setup() throws SQLException{
    jsonObject.put("id", "hello");

    when(dbr.getAllMovies()).thenReturn(jsonObject);
}        

Client client = ClientBuilder.newClient();
WebTarget target = client
        .target("http://localhost:9998/RestServiceMovies/resources");

@Override
protected Application configure() {
    return new ResourceConfig(MoviesResource.class);
}

@Test
public void getAllMoviesTest() throws SQLException {

    String responseGetAllMovies = target("/movies").request().get(String.class);

    Assert.assertTrue("hello".equals(responseGetAllMovies));
}

At this moment I can run the tests but still when I test the getAllMovies() method it makes a call to the real database instead of returning the jsonObject.

I have the feeling that a connection is missing between the mock object and the constructor from the MovieResource class?

4

1 回答 1

3

When you register your resource as a class

new ResourceConfig(MoviesResource.class)

you are telling Jersey to create the instance. If you don't have any DI configured, it will just call the no-arg constructor. In your no-arg constructor, you are just creating the service yourself. It knows nothing about your mock.

What you should do instead is register the resource class as an instance. That way you can pass the mock to the constructor.

MockitoAnnotations.initMocks(this);
return new ResourceConfig()
        .register(new MoviesResource(dbr));

Don't use the Mockito runner. Instead use the MockitoAnnotations.initMocks method. That way you control when the @Mocks are injected. If you use the runner, the injection will not happen in time, as the the configure method is called by the framework before the Mockito injection happens.

于 2016-06-20T15:52:58.900 回答