Java Play 2.4 write test case for class using injection - java

Recently I am using play 2.4 framework for Java project.
In that I am using WsClient Library. That library is injected in my class.
#Inject WSClient wsClient
Now I am trying to write a test case for that class but test case fails because of null pointer error for wsClient variable.
wsClient.url("some url").get()
Can you please help me to resolve this?
following is the test code
// Class
public class ElasticSearch {
#Inject WSClient wsClient;
public Promise<WSResponse> createIndex() {
Logger.info("Entering ElasticSearch.createIndex()");
Logger.debug("WSClient: " + wsClient);
Promise<WSResponse> response =wsClient.url(this.getEsClient()+ "/" +this.getEsIndexName()).setContentType("application/json").put("");
Logger.info("Exiting ElasticSearch.createIndex()");
return response;
}
}
// Test function
#Test
public void testCreateIndex() {
running(fakeApplication(), new Runnable() {
public void run() {
ElasticSearch esearch= new ElasticSearch();
esearch.setEsIndexName("car_model");
assertNotNull(esearch.createIndex());
}
});
}

Before writing the options you have, I suggest to use elastic4s.
This third party lib will help you write a more functional code and give you very nice dsl to write your queries.
One more thing, I don't know what is your used case for using elasticsearch, but I recommend using a different client then the rest api, which will give you more secure connection and more efficient.
You get the NPE, because you instasiate ElasticSearch by your own with new, and don't let guice to the wiring for you, this is why the WSClient is null.
Now for your options,
You have 2 options:
Add WithApplication to your test, which will basically load your application, this will give you the access to Guice injector, from which you can take ElasticSearch class like this you have couple of ways to do it:
As described in play documentation using
import play.api.inject.guice.GuiceInjectorBuilder
import play.api.inject.bind
val injector = new GuiceInjectorBuilder()
.configure("key" -> "value")
.bindings(new ComponentModule)
.overrides(bind[Component].to[MockComponent])
.injector
val elasticsearch = injector.instanceOf[ElasticSearch]
By importing Play
import play.api.Play
val elasticsearch = Play.current.injector.instanceOf(classOf[ElasticSearch])
Using FakeApplication: just get hold of the fake application injector, and use it to get an instance of ElasticSearch class.
I don't like the above options, because you need an application running, which can make your tests very slow.
I suggest to create the WSClient by your self and instantiate ElasticSearch class with it, and run your tests.
val httpClient = NingWSClient.apply()
val elasticsearch = new ElasticSearch(httpClient)
This is a more light solution, and should make your tests run faster.

Related

How to use mockito to mock grpc ServiceBlockingStub to throw StatusRuntimeException(Status.UNAVAILABLE)?

I want to mock my grpc client to ensure that it is resilient to failure by throwing an new StatusRuntimeException(Status.UNAVAILABLE) (This is the exception that is thrown when java.net.ConnectException: Connection refused is thrown to the grpc client). However, the generated class is final, so mock will not work.
How do I get BlahServiceBlockingStub to throw new StatusRuntimeException(Status.UNAVAILABLE) without having to refactor my code to create a wrapper class around BlahServiceBlockingStub?
This is what I have tried (where BlahServiceBlockingStub was generated by grpc):
#Test
public void test() {
BlahServiceBlockingStub blahServiceBlockingStub = mock(BlahServiceBlockingStub.class);
when(blahServiceBlockingStub.blah(any())).thenThrow(new StatusRuntimeException(Status.UNAVAILABLE));
blahServiceBlockingStub.blah(null);
}
Unfortunately I get the below exception as expected:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class BlahServiceGrpc$BlahServiceBlockingStub
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
at MyTestClass.test(MyTestClass.java:655)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.
.
.
Because I tried mocking the final class generated by grpc:
public static final class BlahServiceBlockingStub extends io.grpc.stub.AbstractStub<BlahServiceBlockingStub> {
private BlahServiceBlockingStub(io.grpc.Channel channel) {
super(channel);
}
Do not mock the client stub, or any other final class/method. The gRPC team may go out of their way to break your usage of such mocks, as they are extremely brittle and can produce "impossible" results.
Mock the service, not the client stub. When combined with the in-process transport it produces fast, reliable tests. This is the same approach as demonstrated in the grpc-java hello world example.
#Rule
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
#Test
public void test() {
// This can be a mock, but is easier here as a fake implementation
BlahServiceImplBase serviceImpl = new BlahServiceImplBase() {
#Override public void blah(Request req, StreamObserver<Response> resp) {
resp.onError(new StatusRuntimeException(Status.UNAVAILABLE));
}
};
// Note that the channel and server can be created in any order
grpcCleanup.register(InProcessServerBuilder.forName("mytest")
.directExecutor().addService(serviceImpl).build().start());
ManagedChannel chan = grpcCleanup.register(
InProcessChannelBuilder.forName("mytest").directExecutor().build();
BlahServiceBlockingStub blahServiceBlockingStub
= BlahServiceGrpc.newBlockingStub();
blahServiceBlockingStub.blah(null);
}
When doing multiple tests, you can hoist the server, channel, and stub creation into fields or #Before, out of the individual tests. When doing that it can be convenient to use MutableHandlerRegistry as a fallbackHandlerRegistry() on the server. That allows you to register services after the server is started. See the route guide example for a fuller example of that approach.
You have a few options:
NOT RECOMMENDED: Use Mockito v2 to mock final classes and methods.
NOT RECOMMENDED: Use powermock to mocks final classes and methods.
Recommended: (as already mentioned by Eric in his answer) Use the gRPC Java test framework like GrpcCleanupRule and InProcessServerBuilder. See HelloWorldClientTest for an example.
Recommended: Do over-the-wire gRPC API mocking/simulation. Use a third-party tool that will create over-the-wire API mocks/simulators for your API. For example, Traffic Parrot.
Note why mocking final, in this case, might be a bad idea:
Mocking final classes or methods might be a bad idea, depending on the case. The devil is in the details. In your situation, you are creating a mock of the generated code, so you are assuming how that generated code will behave in the future. gRPC and Protobuf are still rapidly evolving, so it might be risky to make those assumptions, as they might change and you won't notice because you do not check your mocks against the generated code. Hence, it's not a good idea to mock the generated code unless you really have to.
How to mock final classes/methods with mockito:
add dependency Mockito Inline
create file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
with one line: mock-maker-inline
And now you can mock final methods and classes.
Mockito docs about mocking
I ended up with an ugly workaround.
I created a new method and a spy() on the class that has a reference to BlahServiceBlockingStub.
The resulting code ended up looking like:
#Test
public void test() {
MyClass myClass = spy(myClass);
doThrow(new StatusRuntimeException(Status.UNAVAILABLE)).when(myClass).newMethod(any());
// changed to call myClass.newMethod() instead of blahServiceBlockingStub.blah
myClass.myExistingMethod();
}

Appropriate way to implement a cli Application which also uses the service profile with Micronaut

I've no problem in creating a REST Server or a Picocli CLI Application.
But what if I want to have both in one Application?
The thing is, I want to have an Application which provides some business logic via REST Server (no problem there), but in some other cases I want to trigger the business logic via CLI without starting the HTTP Server (eg. for CI/CD).
I'm not sure if I run into problems if I start the app via
PicocliRunner.run(Application.class, args) and if a specific argument is given run the Server with Micronaut.run(Application.class);, since they create a different context.
Does anyone know a proper way to achieve this?
This is how I solved it:
import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.runtime.Micronaut;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
#Command(
name = "RestAndCliExample",
description = "...",
mixinStandardHelpOptions = true
)
public class Application implements Runnable {
private enum Mode {serve, run}
#Parameters(index = "0", description = "Execution mode: ${COMPLETION-CANDIDATES}")
private Mode mode;
public static void main(String[] args) throws Exception {
args = new String[]{"run"};
PicocliRunner.run(Application.class, args);
}
public void run() {
if (Mode.serve.equals(mode)) {
// Start REST API
Micronaut.run(Application.class);
} else {
// TODO run code directly
}
}
}
One way to accomplish this is to #Inject the ApplicationContext into your #Command-annotated class. This allows your command to use the same application context instead of needing to start a separate one.
Then, in your run method, you can start the REST server by obtaining the EmbeddedServer from the application context and calling start on it, or you can execute the functionality directly without the REST server.
See also this answer for more detail: https://stackoverflow.com/a/56751733/1446916

How to avoid external call in JUnit Groovy

Finally I am able to get Groovy class in my Java file and able to perform JUnit on my groovy classes. Now my problem is I want to test my method which triggers RPC calls.but I want to avoid that call in unit test. How should I do that? Below is my sample code for logout how I am proceeding
#Test
public void logoutTest() {
GroovyObject loginOject =new Login();
GroovyObject logoutObject =new Logout();
XMLRPCServerProxy serverProxy = (XMLRPCServerProxy) loginOject.invokeMethod(
"getServerProxy",
"https://urlproxy"
);
String sessionId = (String) loginOject.invokeMethod(
"getSession",
new Object[]{"username","password",serverProxy}
);
logoutObject.invokeMethod("logout",new Object[]{sessionId,serverProxy});
}
You can do so by using mocks. I assume you are testing logoutObject.invokeMethod("logout",new Object[]{sessionId,serverProxy}); method which calls a method on your XMLRPCServerProxy serverProxy. If you a have an option to introduce a dependency on mocking framework such as Mockito you can then create a mock instead of
XMLRPCServerProxy serverProxy = (XMLRPCServerProxy) oginOject.invokeMethod("getServerProxy", "https://urlproxy");
You can mock it
XMLRPCServerProxy serverProxy = mock(XMLRPCServerProxy.class);
when(serverProxy.sendRequest("payload")).thenReturn("result");
If you cannot use a mock library you can extend XMLRPCServerProxy in the test and override a method that does rpc call to do whatever you want (this is effectively what Mockito would do for you)
XMLRPCServerProxy proxyServer = new XMLRPCServerProxy() {
public String request(String payload) {
// your mock code
return "result";
}
};
I'd recommend using Spock for unit-testing Groovy (and Java) code. Latest when it comes to mocking, no Java tool / framework I know is capable of properly mocking Groovy stuff as the language is simply too dynamic to be handled by tools written to hook into Java code.
Spock is written in Groovy and with Groovy in mind when it comes to mocking and stubbing. Spock might look a bit alien if you first look at it, but if you get used to the syntax it is quite amazing what you can do and how easy you can write tests with variying input data and so on.
Spock also is based on JUnit, so every tool that is able to execute and evaluate JUnit tests is also able to cope with Spock tests.

Can I use Inversion of Control with Android components such as Activities and Services?

To facilitate cleaner testing, I would like to use Inversion of Control when developing my Android application. It looks straightforward to do with plain Java objects, but when I want to seed my Activitys and Services with mock data, things start to look problematic as I don't have the ability to pass those component's dependencies to their constructor.
As an example, suppose I wanted to have my Activity use a real HttpUrlConnection during normal use, but for testing, I want to have it use a mock HttpUrlConnection that does not actually connect to the internet. Is there a way I could accomplish this through IoC for an Activity?
I realize there are dependency injection options such a Factories, and libraries such as Dagger that could help me out, but I was curious if there were other ways to accomplish this.
Since Constructor-Injection for Service or Activity is not possible in Android because these classes are instantiated with a parameterless constructor by the Android runtime you need some kind of factory that creates the external objects for you. To solve this I would create a Factory-Interface which can have a mock implementation like this:
public class MyService : Service {
public static IFactory myFactory = new MyFactory();
// the non-mocked version used as Default
void myLocalFunction() {
...
HttpUrlConnection connection = myFactory.createHttpUrlConnection();
...
}
}
public MyServiceTest : ... {
class MyMockedFactory : MyFactory {
HttpUrlConnection createHttpUrlConnection(){return new MockedHttpUrlConnection();}
}
public myTest() {
MyService.myFactory = new MyMockedFactory();
.... do the test ...
}
}

JUnit Test of Code that uses GAE/J URLFetchServiceFactory.getURLFetchService()

I've got some code I'm deploying to Google App Engine - Java (GAE/J) that makes use of the URLFetchService. I'd like to use JUnit to test this code. Per the testing documentation, it appears I should have a test that uses their LocalURLFetchServiceTestConfig class ROUGHLY as follows:
public class MyRemoteServiceTests {
private static final LocalURLFetchServiceTestConfig urlConfig = new LocalURLFetchServiceTestConfig();
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(urlConfig);
#Before
public void setUp() throws Exception {
service = new SampleService();
helper.setUp();
}
#After
public void tearDown() throws Exception {
service = null;
helper.tearDown();
}
#Test
public void testThatCallsCodeThatUsesUrlFetch() {
Object data = service.getRemoteDataUsingUrlFetch("foo", "bar");
Assert.assertNotNull(data);
}
}
I'm finding that this test continues to fail despite using the "helper" as suggested in the GAE/J documentation on testing: "The API package 'urlfetch' or call 'Fetch()' was not found.".
I was assuming that using the "helper" would somehow setup the GAE environment such that when I call URLFetchServiceFactory.getURLFetchService() from within my getRemoteDataUsingUrlFetch method, the interface returned would be an instance of LocalURLFetchService that would just "work" but that seems NOT to be the case.
How can I test this code?
Am I missing something? (I'm pretty new to GAE...)
Do I have to refactor my getRemoteDataUsingUrlFetch so that it doesn't use URLFetchServiceFactory.getURLFetchService() because that makes it untestable locally??? (That sounds like it would really suck...)
Any help/suggestions much appreciated!
Actually, it turns out my problem was failure to include two additional jars that ARE mentioned on the Local Unit Testing page of the documentation. RTM FTW!
appengine-local-runtime.jar
appengine-api-stubs.jar
afaik, the LocalURLFetchService doesn't configure the GAE like you expect. It is more of a way to fetch URL from the local dev and then process the contents however. (Similarly even the LocalDatastoreService and LocalMemcacheService operate on isolated spaces within the test environment)
One way to test your code is to refactor the getRemoteDataUsingUrlFetch() to take maybe the contents of the Url response. somewhat like,
URLFetchResponse resp = LocalURLFetchService.fetch(status, request)
getRemoteDataUsingUrlFetch(foo, bar, resp)

Categories