Can I mock Kotlin service into java Junit test - java

I'm currently writing Junit test with Mockito in java. But one microservice is written in Kotlin.
I try to mock the kotlin service, but it doesn't work as I excepted.
I plan to return a customize response inside the test, I checked it with debugger, instead of returning the response, it always runs into the kotlin function(getFile).
#Mock
private FileService fileservice; // this service written in Kotlin
#Before
public void setUp() {
Response respone = new Response(...);
when(fileservice.getFile(any())).thenReturn(response);
}

The best approach is to use mocking library designed for Kotlin, there is few options for this:
If still needed to stick to mockito, there is official mockito support for kotlin, more details here: https://github.com/mockito/mockito-kotlin
Also there is mockk library that specially designed for kotlin, and it better fits than mockito: https://mockk.io/
Also many java libraries using byte-code generated proxies like mockito does, while kotlin makes every class final by default, there is a kotlin plugin named all-open, which can make all needed classes open: https://kotlinlang.org/docs/all-open-plugin.html

Related

How to migrate PowerMockito whenNew thenThrow to Mockito Inline MockedConstruction

We're migrating all our code away from PowerMock to Mockito Inline, I've mostly been able to migrate all cases but I don't know how throw an exception when an instance of a specific class is created, using Mockito MockedConstruction.
i.e I need to migrate to Mockito Inline from this:
whenNew(MyClass.class).withAnyArguments().thenThrow(new MyException("fail"));
I've read the docs and I can't find how to do it.
I've tried this:
try (MockedConstruction<MyClass> ignored = mockConstruction(MyClass.class,
(mock, context) -> { when(new MyClass(any())).thenThrow(new MyException("fail"));})
) {
stuffToTest();
}
I've also tried the suggested solution here but it doesn't work.

JUnit without inversion of control

Currently the JUnit5 Framework works with Inversion of Control. I.e. you annotate a test method with #Test and then JUnit scans your classpath (in the simplest case)
Now is there a way for me to be in charge of calling the test cases through JUnit APIs? Maybe by hooking my test implementations to some test registry provided by JUnit?
I'm pretty new to JUnit - how did older versions go about this?
The reason I'm asking is that normally to execute my test cases, I'd have to run something along the lines of
java -jar junit-platform-standalone.jar --class-path target --scan-class-path
on the command line. My situation requires me to run the test cases through by executing one of my own classes, like that e.g.
java /com/example/MyTestCassesLauncher
EDIT: to clarify, I need one of my own classes to be hosting/launching my test cases, something like this:
// Maybe this needs to extend one of JUnit's launchers?
public class MyTestCassesLauncher {
public static void main(String[] args) {
JUnitLauncher.launchTests(new MyTestClass());
}
}
where JUnitLauncher.launchTests is some kind of API provided by the platform. I'm not looking for a method with that exact same signature but a mechanism that would allow me to ultimately call my own MyTestClassesLauncher class to run the tests.
Thanks in advance.
Not sure what you arę actually trying to achieve but in Junit5 to change behaviour of your tests you can use Extensions mechanism, similar to Junit4 RunWith but more powerful
Such custom extension can provide some additional logic like in this logging example
public class LoggingExtension implements
TestInstancePostProcessor {
#Override
public void postProcessTestInstance(Object testInstance,
ExtensionContext context) throws Exception {
Logger logger = LogManager.getLogger(testInstance.getClass());
testInstance.getClass()
.getMethod("setLogger", Logger.class)
.invoke(testInstance, logger);
}
}
The way Junit controls it's flow is Junit problem - you should not modify framework but extend it

Unit Testing a Public method with private supporting methods inside of it?

When trying to perform test driven development on my JSF app, I have a hard time understanding how to make my classes more testable and decoupled.. For instance:
#Test
public void testViewDocumentReturnsServletPath(){
DocumentDO doc = new DocumentDO();
doc.setID(7L);
doc.setType(“PDF”);
DocumentHandler dh = new DocumentHandler(doc);
String servletPath = dh.viewDocument();
assertTrue(servletPath, contains(“../../pdf?path=“);
}
This is only testable (with my current knowledge) if I remove some of the supporting private methods inside viewDocument() that are meant to interact with external resources like the DB.
How can I unit test the public API with these supporting private methods inside as well?
Unit testing typically includes mocking of external dependencies that a function relies on in order to get a controlled output. This means that if your private method makes a call to an API you can use a framework like Mockito to force a specific return value which you can then use to assure your code handles the value the way you expect. In Mockito for example, this would look like:
when(someApiCall).thenReturn(someResource);
This same structure holds if you wish to interact with a database or any other external resource that the method you are testing does not control.

JUnit 5, pass information from test class to extension

I am trying to write an extension for Junit5 similar to what I had for Junit4 but I am failing to grasp how to do that in the new (stateless) extension system.
The idea in the previous version was that user could pass information into extension class and hence change the way it behaved. Here is a pseudo snippet showing approximately what is used to do:
public void MyTest {
// here I can define different behaviour for my extension
#Rule MyCustomRule rule = MyCustomRule.of(Foo.class).withPackage(Bar.class.getPackage).alsoUse(Cookies.class);
#Test
public void someTest() {
// some test code already affected by the #Rule
// plus, user has access to that class and can use it, say, retrieve additional information
rule.grabInfoAboutStuff();
}
}
Now, I know how to operate JUnit 5 extension, what lifecycles to use etc. But I don't know how to give the test-writer the power to modify my extension's behaviour with JUnit5. Any pointers appreciated.
As of JUnit Jupiter 5.0.1, it is unfortunately not possible to pass parameters to an Extension programmatically like you could for rules in JUnit 4.
However, I am working on adding such support in JUnit Jupiter 5.1. You can follow the following issue if you like: https://github.com/junit-team/junit5/issues/497
In the interim, the only way to pass information to an extension is for the extension to support custom annotations and extract the user-supplied information from there. For example, I allow users to provide a custom SpEL expression in the #EnabledIf annotation in the Spring Framework, and my ExecutionCondition extension pulls the expression from the annotation using reflection.
followup on the (accepted) answer from Sam as in the meantime the referred bug has been implemented with junit 5.1
use #RegisterExtension
see https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic

How do I test Java code that uses JAR?

I have Java code that uses JAR:
public class Version {
public String getVersion() {
// Use Java Package API to return information specified in the manifest of this JAR.
return getClass().getPackage().getImplementationVersion();
}
}
How do I run JUnit test for this code?
It fails in development build (in Eclipse) since there is no JAR file yet.
It fails in production build (in Gradle) since there is no JAR file yet.
You always need to mock the dependencies for your unit testing. Boundary is unit test your code and not the jar itself. Mockito framework is good and there are other frameworks that do the job.
Chances are, that this can't be properly mocked (and thus: not unit tested). The point is that you are actually calling a method on "this". But you can't test some object ... and mock it at the same time.
You see, if your production code would look like this:
public String getVersion() {
return someObject.getClass().....
}
then you could create a mock object; and insert that into your Version class. But even then, the method getClass() is final within java.lang.Object; and therefore you can't be mocking it anyway.
[ Reasonable mocking frameworks like EasyMock or Mokito work by extending classes and overriding the methods you want to control. There are frameworks like PowerMock that do byte code manipulation and that allow for this kind of mocking - but you should never ever use such libraries; as they have really bad side effects (like breaking most coverage libraries) ]
What might work:
class Version {
private final Package packageForVersionCheck;
public Version() {
this(getClass().getPackage()));
}
Version(Package somePackage) {
this.packageForVersionCheck = ...
}
public String getVersion() {
return this.packageForVersionCheck.getImpl....
Now you can use dependency injection to provide a "mocked" package that returns that string. But well, that looks like a lot of code for almost no gain.
Long story short: sometimes, you simply can't write a reasonable unit test. Then do the next best thing: create some "functional" test that is automatically executed in a "customer like" setup; and make sure that you have an automated setup to run such tests, too.

Categories

Resources