How to avoid external call in JUnit Groovy - java

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.

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();
}

Java pass arguments dynamically to a junit test

I'm doing a special junit test, that the params are introduced in the front-end of the application by the user and received in back-end of the application. And i want to generate junit test that use that information as parameters.
I saw some guide (like mykong guide and tutorial points) but most of them use static parametrized and i want some dynamic thing. I already tried to use junit annotations, do a set or pass the params to the junit class, use mockito methods but nothings work as dynamic process
Can someone point me to the right direction?
Right now i have something like that
public void run (Object foo) //Class that contains the information introduced by the user
JUnitCore junit1 = new JUnitCore();
Result result4 = JUnitCore.runClasses(GeneratedTest.getClass()); //Junit class
//I tried: do a setFoo on the GeneratedTest ; pass the foo on the constructor;
for (Failure failure : result4.getFailures()) {
System.out.println(failure.toString());
}
Probably not the nicest solution, but maybe an acceptable workaround:
generate your unit test so that it fetches parameters from System properties
run the generated JUnit test in its own JVM, and pass the parameters/properties on the command line

Mockito Mock and Spy in SpringBoot App

I have read quite a few articles/blog/StackOverflow questions, but the confusion regarding Mockito mock and spy still remains. So, I started trying implementing them in a small Spring Boot app. My app has a ProductRepository extending CrudRepository.
Currently I'm testing the repository by mocking ProductRepository as follows
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {RepositoryConfiguration.class})
public class ProductRepositoryMockTest {
#Mock
private ProductRepository productRepository;
#Mock
private Product product;
#Test
public void testMockCreation(){
assertNotNull(product);
assertNotNull(productRepository);
}
#Test
public void testSaveProduct() {
assertThat(product.getId(), is(equalTo(0)));
when(productRepository.save(product)).thenReturn(product);
productRepository.save(product);
//Obviously this will fail as product is not saved to db and hence
//#GeneratedValue won't come to play
//assertThat(product.getId() , is(not(0)));
}
#Test
public void testFindProductById() {
when(productRepository.findOne(product.getId())).thenReturn(product);
assertNotNull(productRepository.findOne(product.getId()));
assertEquals(product, productRepository.findOne(product.getId()));
}
}
The test passes. Is this the right way? I also want to understand how to use #Spy here and Why should I need it? Any specific scenarios related to this is most welcome.
Thanks in advance.
I have taken a look at your tests and there are few things to keep in mind (this is based on my experience so the final call is up to you):
1) Hamcrest - If that is possible i would strongly recommend using Hamcrest for your assert implementations.
First of all it is much more versatile and feature rich than the standard junit assertions.
Second of all you may one day have the need (as i did on one of my projects) to switch from junit to testng for examle.
Having all your assertions based on a xunit-neutral implementation, the switch will not be so painful.
2) Assertions - Instead of assertNull, assertEquals go for the hamcrest's assertThat(String description, T value, Mathcer<T> matcher);
Thanks to that you will get clear error messages when a test breaks.
3) Small tests - In your Repository test.. do not put all the cases in one test.
Try to create many small and simple tests for cases like: findOne.. count.. findAll etc.
Again it will be easier to find the problem when a small test like that breaks.
And if more cases will come you wont end up with a 200+ lines of a test case which is unacceptable
4) Naming - Do not name your tests as.. testXYZ.
It is obvious that these are test methods.
I would recommend using the BDD way of naming: shouldX_whenY_givenZ.
F.e. shouldReturnZeroCount_givenNoEntitiesInTheDatabase
5) Structure - Try to split each of your test implementation in three explicit sections, including comments for best result:
public void should..() throws Exception{
// Arrange
// when().then()
// mock()
// Act
// classUnderTest.process()
// Assert
// assertThat(..)
}
6) Do not split your test classes between Mock / Spy test. HAve one ImplTest.
7) Never mock a class which you are testing. In the worst case scenario use Spy if you have to mock some of the methods of the class under test.
The point of mocking is to isolate the implementation in the class under test, so that only that classes logic is invoked during the test.
Mock only dependencies of the class.

How i can get the method in the setup method in spock?

how i can get the method of the running feature? I want to prepare the database with different datasets. This datasets should be defined with annotations like this:
#PrepareDB("dataset1")
def "feature 1"() {
}
and should be used in the setup method like this:
def setup() {
def dataset = currentTestMethod.getAnnotation().value //pseudo method
prepareDB(dataset)
}
I did the same with JUnit4. I used #Rule to get current method name and get the annotation value per reflection. How i can do this in spock?
Update:
I found a solution myself. With the TestWatcher from JUnit4 its possible to get an annotation fom the current running test method:
#Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
println description.getAnnotation(PrepareDB.class).value()
};
};
I recommend to implement the database logic as an annotation-driven Spock extension or a JUnit rule, both of which provide easy access to the annotations of the executed feature method.
To answer your question, to get at the annotation from the setup method, you'd use (as of Spock 0.7) specificationContext.iterationInfo.parent.featureMethod.reflection.getAnnotation(PrepareDB). In Spock 1.0-SNAPSHOT and beyond, this has changed to specificationContext.currentFeature.featureMethod.getAnnotation(PrepareDB).

gwt-log and gwt-test-utils not playing nice together

I've got a project that has gwt-log logging lines scattered throughout. Now I'm trying to write some unit tests and nothing seems to be working.
Any class I test that uses the gwt-log facility causes the following exception to be raised:
Caused by: com.googlecode.gwt.test.exceptions.GwtTestConfigurationException:
A custom Generator should be used to instanciate
'com.allen_sauer.gwt.log.client.LogMessageFormatter',
but gwt-test-utils does not support GWT compiler API,
so you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
I have no need for the logger to function during unit tests, I'd prefer to mock it away.
I've attempted to use Mockito to mock the logger, in a few different ways... obviously I have no idea what I'm doing here, none of the following code snippets helped the situation:
public class ClockTest extends GwtTest {
#Mock private LogMessageFormatter lmf;
...
or
...
#Before
public void init() throws Exception {
LogMessageFormatter lmf = mock(LogMessageFormatter.class);
...
Any clues on how to work this out would be most appreciated!
Colin is right, you have 2 ways to deal with your error :
1) Mock the LogMessageFormatter, or at a higher level, mock your Logger instance. gwt-test-utils provides a simple API for mocking with both Mockito or EasyMock : http://code.google.com/p/gwt-test-utils/wiki/MockingClasses
2) provide your own GwtCreateHandler to instanciate the LogMessageFormatter, or at a higher your own Logger instance.
Internally, gwt-log relies on GWT's deferred binding to instanciate a LogMessageFormatter object based on your configuration, which is parsed at compile time. It use GWT's generator API to create the LogMessageFormatter class, but gwt-test-utils is not able to use those kind of Generators.
You'll have to do it "by hand", with gwt-test-utils deferred binding support : GwtCreateHandlers.
Your "LoggerGwtCreateHandler" could use JDK's InvocationHandler and Proxy classes to write a proxy for the Logger interface which would simply silent each method call, since I guess you won't care about any log call in your tests.
Here is a discussion on how to write a GwtCreateHandler : https://groups.google.com/forum/?fromgroups#!topic/gwt-test-utils-users/r_cbPsw9nIE
From the error message you posted:
you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
These are the two options you have to proceed. I've only just begun to work with gwt-test-utils, but the main premise is that it doesn't run the GWT compiler or Dev Mode, so it needs other ways to handle implementing 'magic' features like GWT.create. Its method is to either require you to mock the instance (this should be a fairly common idea in most of your tests for other objects involved in testing) or to provide something like a generator, and hook it up using GwtTest.addGwtCreateHandler.
Building a mock logger shouldn't be too bad, nor should implementing GwtCreateHandler - you just need to make something that has all the log methods. If you want the logging to work, then those methods need to actually invoke some other logger, like java.util.Logger, log4j, slf4j, etc but that is not required for just getting the tests to run (but may be handy for making sure that you logging works, or finding out why your test is failing.
for those still in pain with this damn problem here is what I managed to get (With a lot of pain too ...). It'll solve the conflict between Gwt-test-utils and Gwt-log.
You're of course welcome to modify the format method ;) :
#Before
public void correctLog() {
this.addGwtCreateHandler(new GwtCreateHandler() {
#Override
public Object create(Class<?> classLiteral) throws Exception {
if (classLiteral.isAssignableFrom(LogMessageFormatter.class)) {
return new LogMessageFormatter() {
#Override
public String format(String logLevelText, String category,
String message, Throwable throwable) {
return message + " : " + throwable.getLocalizedMessage();
}
};
}
return null;
}
});
}

Categories