How to unit test the below method with the EasyMock. I tried to mock WebResource but it is returning me a NullPointerException.
public void connect()
{
Client client = setUpClient();
WebResource jobBuilder = client.resource("URL");
String jobXml = jobBuilder.accept(MediaType.APPLICATION_XML)
.type(MediaType.APPLICATION_JSON)
.entity(request)
.post(String.class);
}
public Client setUpClient()
{
ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(JacksonJsonProvider.class);
Client client = Client.create(cc);
return client;
}
You clearly have to read up on the Inversion of Control Principle (http://en.wikipedia.org/wiki/Inversion_of_control), if not for the sake of the better designed code, then for the sake of unit testing. The client object in the method above is created inside the method itself, using the static factory method Client.create(). There is no good way to inject a mock collaborator with that approach. You should either allow injection of the client via a setter or a constructor, or delegate its creation to some sort of a factory.
If you use the 1st approach, you can inject the mock client directly via the setter or constructor during the unit test setup.
If you use the 2nd approach, you can provide a factory that would return a mock client when called.
EDIT 5/03:
Here's example of making your code testable by providing an object factory for a 3rd party library object:
public class ClassToTest {
private ClientFactory factory;
public ClassTotest() {
this(new ClientFactory());
}
public ClassToTest(ClientFactory factory) {
this.factory = factory;
}
public void connect() {
Client client = factory.getClient();
WebResource jobBuilder = client.resource("URL");
String jobXml = jobBuilder.accept(MediaType.APPLICATION_XML)
.type(MediaType.APPLICATION_JSON)
.entity(request)
.post(String.class);
}
}
public class ClientFactory() {
public Client getClient() {
ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(JacksonJsonProvider.class);
Client client = Client.create(cc);
return client;
}
}
Now, in your application code you can instantiate your class using the no-argument constructor. In the unit test you would use the other constructor. This way you would be able to inject a mock Client that you would script for the purpose of testing WebResource.
Hope this helps.
Related
I am trying to write a test for my service that sets up a connection with another service that returns me items from the database. My problem is that I set the connection properties in the test and start the service. How can this be mock or something similar?
My start service method:
public void doStartService() {
super.doStartService();
PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
manager.setDefaultMaxPerRoute(maxConnectionsPerRoute);
manager.setMaxTotal(maxConnections);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setSocketTimeout(socketTimeout)
.setRedirectsEnabled(false).build();
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultRequestConfig(requestConfig);
builder.setConnectionManager(manager);
client = builder.build();
}
My setup test method and one test method:
private ProductCatalogIntegrationService service;
#Before
public void setup() {
service = new Service();
service.setConnectTimeout(10000);
service.setSocketTimeout(10000);
service.setMaxConnections(10);
service.setMaxConnectionsPerRoute(10);
service.setUrl("http://localhost:8888/products");
service.doStartService();
}
#Test
public void testReturnProductById() {
service.setProductById(GET_PRODUCT_BY_ID); // set url from get product by id, by this url my other service goes to the database
jsonItem = service.getProductById("1"); //get product by id 1
assertEquals(jsonItem.getId(), FIRST_PRODUCT_ID); // I compare the id on which I made the request to the database, so that I came and was wrapped in a class wrapper
}
How to do it correctly, so as not to configure the connection in the tests?
Javalin would be an excellent tool for mocking the real service as it allows for state assertions in your tests.
Wiremock can be used as well. But it leads to hard to maintain behavioral tests (verify).
The protobuf definition is as follows:
syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
I need to use Mockito along with JUnit testing.
The encouraged way to test a service is to use the in-process transport and a normal stub. Then you can communicate with the service like normal, without lots of mocking. Overused mocking produces brittle tests that don't instill confidence in the code being tested.
GrpcServerRule uses in-process transport behind-the-scenes. We now I suggest taking a look at the examples' tests, starting with hello world.
Edit: We now recommend GrpcCleanupRule over GrpcServerRule. You can still reference the hello world example.
The idea is to stub the response and stream observer.
#Test
public void shouldTestGreeterService() throws Exception {
Greeter service = new Greeter();
HelloRequest req = HelloRequest.newBuilder()
.setName("hello")
.build();
StreamObserver<HelloRequest> observer = mock(StreamObserver.class);
service.sayHello(req, observer);
verify(observer, times(1)).onCompleted();
ArgumentCaptor<HelloReply> captor = ArgumentCaptor.forClass(HelloReply.class);
verify(observer, times(1)).onNext(captor.capture());
HelloReply response = captor.getValue();
assertThat(response.getStatus(), is(true));
}
I have an OSGi service which I have exposed with CXF as a simple web service and for which I have created a client which invokes its methods. The methods of this service accept as one of their arguments a signed ticket which identifies the client performing the request. In order to inject this ticket to all requests coming from my client I have created a CXF out interceptor, which I have bound to the SETUP phase, and which is responsible for the injection of the ticket in the outgoing message.
In case the ticket injected by my interceptor has expired, the service will throw an exception which I would like to be able to catch, get a fresh ticket and repeat the request with this fresh ticket in order to completely abstract the ticket-management functionality from the rest of my code. I have therefore created an in fault interceptor, which I have bound to the PRE_LOGICAL phase and in which I am able to identify whether the specific exception type I am interested in has been thrown. I am however unsure as to how I can repeat the request and return the result of the second request instead of the first one. Does CXF offer a way for me to do this?
Since I wasn't able to find a way to repeat the request through a fault interceptor I ended up using an InvocationHandler to allow me to control the request (effectively wrapping the proxy I get from CXF in another proxy). What I ended up with is something like the following:
ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
// Configure factory
MyService serviceClient = (MyService) factory.create(MyService.class);
MyService proxy = (MyService) Proxy.newProxyInstance(
ServiceInvocationHandler.class.getClassLoader(),
new Class[] { MyService.class },
new ServiceInvocationHandler(serviceClient));
Where the ServiceInvocationHandler is:
public class ServiceInvocationHandler implements InvocationHandler {
private final Object proxied;
private SignedTicket ticket;
public ServiceInvocationHandler(Object proxied) {
this.proxied = proxied;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object retVal = null;
try {
// Generate a ticket if the one held locally by this class is null
// and inject it in the method arguments
retVal = method.invoke(proxied, args);
} catch (Throwable t) {
if (t.getCause() instanceof InvalidTicketException) {
// Get a fresh ticket and inject it in the method arguments
retVal = method.invoke(proxied, args);
}
}
return retVal;
}
}
I am trying to learn dependency injection. By example I have the following simple web service client I wrote that talks to a to a web service.
public class UserWebServiceClient
{
private Client client;
public UserWebServiceClient(String username, String password)
{
ClientConfig clientConfig = new DefaultApacheHttpClientConfig();
this.client = ApacheHttpClient.create(clientConfig);
this.client.addFilter(new HTTPBasicAuthFilter(username, password));
}
private WebResource getWebResource()
{
WebResource resource = this.client.resource("http://mywebservice/.......");
return resource;
}
public void createUser(String s) throws StorageAPIException
{
getWebResource().post(...);
}
}
Is this a candidate for dependency injection? Should I be injecting the client?
I don't want to push the complexity of that up to the user. I think Im getting a bit confused about when to use DI.
Yes, if I came across this code I'd change it to be:
public class UserWebServiceClient
{
private Client client;
public UserWebServiceClient(Client client)
{
this.client = client;
}
...
}
Injecting the Client allows me to pass any implementation of Client I choose including mock instances in order to test this class.
Additionally in this case, changing the class in this way also allows the use different implementation of ClientConfig.
In short, the class just became a whole load more reuseable.
It's best to use constructor injection as opposed to field injection. Doing so enables you to swap bindings for testing. It's also good to separate credentials for the same reason.
Your bindings would then be made available via Module or some form of configuration.
With Guice it may look something like this...
public class UserWebServiceClient
{
private Client client;
#Inject
public UserWebServiceClient(Client client)
{
this.client = client;
}
...
}
Your module
public class RemoteModule extends AbstractModule {
public void configure() {
}
#Provides
public Client provideClient(#Named("username") String username,
#Named("password") String password) {
ClientConfig clientConfig = new DefaultApacheHttpClientConfig();
Client client = ApacheHttpClient.create(clientConfig);
client.addFilter(new HTTPBasicAuthFilter(
username, password));
return client;
}
#Provides
#Named("username")
public String provideUsername() {
return "foo";
}
#Provides
#Named("password")
public String providePassword() {
return "bar";
}
}
I was wondering how should I go about injecting a mocks - we have bunch of classes that do server calls, however our CI system can not access external resources and thus will not make a call to a server. Thus, the call has to be simulated and hardcoded values (such as response codes) needed to be return.
So, here is a snippet of a code:
HttpPost httpRequest = new HttPost(uri);
//some code here
try{
httpRequest.setEntity(entity);
HttpResponse response = httpClient.execute(httpRequest);
...
//other, irrelevant, code is here
So, is it possible to inject a mock into httpClient.execute(httpRequest) and return hardcoded response entity from a test unit?
Thank you
Usually mocking some object looks like this:
public class TestClass {
private HttpServer server;
public HttpServer getServer() {
return server;
}
public void setServer(HttpServer server) {
this.server = server;
}
public void method(){
//some action with server
}
}
And test class:
public class TestClassTest {
//class under test
TestClass test = new TestClass();
#org.junit.Test
public void testMethod() throws Exception {
HttpServer mockServer = Mockito.mock(HttpServer.class);
test.setServer(mockServer);
//set up mock, test and verify
}
}
Here you some useful links:
Code example
Official documentation