Get past static field of jUnit:s #BeforeClass - java

Is there any way around the classic problem of
public class SomeClass implements SomeOtherInterface {
private static SomeInterface some;
public SomeClass(SomeInterface someInterface) {
some = someInterface;
}
#BeforeClass
public static void doSomethingWithInterface() {
System.out.println(someInterface.someValue()); // prints null
}
}
other than exchanging
System.out.println(someInterface.someValue()); // prints null
with
System.out.println(SomeInterface.someValue());
if someValue is static. The problem is that this is for an framework (extension), and and an implementation of SomeInterface is to be provided by the user.

You set the value of the static member just in the constructor. So before not having at least one object of that class, you won't be able to access someValue(). In Junit the #Before annotation might be useful which is executed before each test and is not static.

Related

How Functions can be called from java enum?

I'm trying to understand how the static method calls from a Java enum works.
To see the full code of this "Working example"
I have the following scenario working, I don't know why
public enum Condition {
GREATER_THAN(PredicateBuilder::generateGreaterThan, ">"),
more values...
private Condition(BiFunction<PredicateBuilder, PredicateContent<?>, Predicate> predicate, String operator) {
this.operator = operator;
this.predicate = predicate;
}
This is the predicate builder, it's an interface implemented by a #Component from Spring:
#Component
public class PredicateLogicalBuilder<V extends Comparable> implements PredicateBuilder<V> {
#Override
public Predicate generateGreaterThan(PredicateContent<V> predicateContent) {
return predicateConversion(predicateContent,Condition.GREATER_THAN);
}
}
The static reference in above Condition enum doesn't complain about:
Non-static method cannot be referenced from a static context
and I don't why because now I'm trying to do something similar and it fails because the static reference of a method isn't static. In the code above is not static either.
Code I'm trying:
public interface MethodCalls<T> {
void randomMethod(T content);
}
#Component
public class TestEnumMethoCalls implements MethodCalls<SomeBean> {
#Override
public void randomMethod(SomeBean content){
System.out.println("Works!!!!");
}
}
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final Function<SomeBean,Void> method;
private NotificationType(Function<SomeBean,Void> method){
this.method=method;
}
}
public class TestClass{
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(new SomeBean())
}
}
This piece of code fails saying the Non-static method cannot be referenced from a static context:
ENUM_TEST_1(MethodCalls::randomMethod);
I would like to have 2 answers:
Why the code of the "Working example" works.
If it's mandatory for my current test to use the instance of the MethodCalls how can be injected with DI to the enum (is a static context so I understand it might be tricky if not impossible).
Thanks for the help, now I understood why my "working example" works and how to "Fix" my current issue:
To fix it I have to pass an instance of the implementation of the interface as it's pointed out that enums can only access static methods or an instance of the object to access the method that way.
Final Code
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final BiFunction<MethodCalls,SomeBean,Void> method;
private NotificationType(BiFunction<MethodCalls,SomeBean,Void> method){
this.method=method;
}
}
So when I call the apply it looks like this:
public class TestClass{
#Autowired MethodCalls methodCalls;
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(methodCalls,new SomeBean())
}
}
I someone finds out a cleaner way to do this, I would apreciate it.

How to mock enum singleton with jmockit?

I have a dependency on an enum singleton class like
public enum SingletonObject {
INSTANCE;
SingletonObject() {
// some annoying initialization
}
public callDB() {
this.num = num;
}
}
I am trying to test a class like
public class MyClass {
public void doSomething() {
// some code
SingletonObject.INSTANCE.callDB();
}
}
Following this answer, I've tried simply testing the mock with the following code, but I seem to be running into problems with the enum calling its constructor
public class MyClassTest {
#Mocked
private SingletonObject singleton;
#Before
public void setup() {
Deencapsulation.setField(SingletonObject.class, "INSTANCE", singleton);
}
#Test
public void test() {
assertSame(singleton, SingletonObject.INSTANCE);
}
}
Using an interface seems somewhat promising, but I question whether that is the best way of going about this problem.
It looks like PowerMockito is promising as well, but I would like to save that as a last resort for various reasons.
So how can I mock this enum singleton without invoking its constructor?
Try something like this. This creates a partial-mock of 'MyClass' and a Mock SingletonObject, calls the (real) doSomething method of MyClass, and confirms that the (mock) callDB() method of SingletonObject is invoked by it precisely once.
#Test
public void testdoSomething(
#Mocked final SingletonObject singleton)
{
final MyClass clz = new MyClass();
new Expectations(clz)
{
{
SingletonObject.INSTANCE.callDB();
times = 1;
}
};
clz.doSomething();
}

How to implement doNothing() for static void method?

Am trying to mock one static void method, I tried PowerMock but always getting NullPointer exception.
We are trying to mock the below call -
public Class XYZ{
public void method1(){
....
SampleClass.methodTypeStatic1().methodTypeStatic2("xyz", "mno", classVeriable);
}
And the main class is -
public class SampleClass implements SampleClassParent{
private static SampleClass var1;
public static SampleClass methodTypeStatic1(){
if (var1 == null) {
//Do something on var1
}
return var1;
}
public void methodTypeStatic2(String localVar1, String localVar2, DifferentStaticClass localVar3) {
//Do something
}}
Am trying to mock the call like this way in my test class -
#RunWith(PowerMockRunner.class)
#PrepareForTest({SampleClass.class})
public class XYZTest{
#InjectMocks
XYZ xyzTestService;
#Test
public void testMethod1(){
...
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.doNothing().when(SampleClass.methodTypeStatic1());
xyzTestService.method1();
}
Also to be mentioned SampleClass.class is not a part of our code, we have imported this external class into our code base to perform some task.
If you want to mock a non-void method, you need to define the behaviour for this method on the mock. You get the doNothing for free (as this is what mocking does),
however you need to define what the method is supposed to return.
Your test could look like this:
#Test
public void testMethod1() {
SampleClass sample = new SampleClass();
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.when(SampleClass.methodTypeStatic1()).thenReturn(sample);
XYZ xyzTestService = new XYZ();
xyzTestService.method1();
}
You didn't not mention any #Mock annotations, so using #InjectMocks does nothing for you besides creating the XYZ object.

Static initializer doesn't run during JUnit tests

I have an interesting JUnit problem here (JUnit 4.12). I have a base class that only has static methods. They have to be static, because of the way they're used. I inherit other classes from the base class. So, if the base class is Base, we have ChildA and ChildB.
Most of the methods are contained in the base class, but it has to know which child it actually is (just calling the methods as the base class is invalid). This is done via a static data member in the base class:
public class Base {
protected static ChildType myType = ChildType.Invalid;
...
}
Each child sets the data member via a static initializer, thus:
static {
myType = ChildType.ChildA;
}
Then when the methods are called, the base class knows what type it is and loads the appropriate configurations (the type is actually a configuration name).
This all works perfectly when running the application. Stepping through it in the debugger and through log messages, I can see the appropriate types are set and the methods load the appropriate configurations based on the child type.
The problem arises when using JUnit. We have some JUnit tests to test each of the base class methods. Since calling the methods on just the base class is invalid, we call the methods on the child classes, thus:
bool result = ChildA.methodTwo();
This ''always fails''. Why? The static initializer never gets called. When running the code as an application, it gets called, and everyone is happy. When I run it as a JUnit test, the static initializer is skipped and the methods have invalid data. What is JUnit doing that skips the static initializer? Is there a way around it?
Details
In reality, we're not calling the method as I posted above. I just wanted the example to be as clear as possible. In reality, we have a Web Service written with the Jersey framework. The method called is one of the REST endpoints.
#POST
#Produces(MediaType.TEXT_PLAIN)
public String methodPost() {
...
return new String( itWorked ? "success" : "fail" );
}
And we call it like this (sorry about the ugly syntax, it's just the way it works):
#Test
public void testThePost() throws Exception {
javax.ws.rs.core.Response response = target("restapi/").request().post(Entity.entity(null, MediaType.TEXT_PLAIN));
assertEquals( 200, response.getStatus() );
}
All the GET tests work, and the static initializer is called on all of them. It's just this POST that fails, and only when running the JUnit test.
You are trying to implement polymorphic behavior for static methods, a language feature that is present in other programming languages, but is missing in Java.
[myType is] a protected member of the base class
Relying on static initializers to set static fields in the base class is very fragile, because multiple subclasses "compete" for a single field in the base class. This "locks in" the behavior of the base class into the behavior desirable for the subclass whose initializer ran last. Among other bad things, it denies a possibility of using multiple subclasses along with the Base class, and makes it possible for ChildA.methodTwo() to run functionality designed for ChildB.methodTwo(). In fact, there is no ChildA.methodTwo() and ChildB.methodTwo(), there's only Base.methodTwo() that relies on information prepared for it by the static initialization sequence.
There are several solutions to this problem. One possibility is to pass Class<Child###> object to methods of the base class:
class Base {
public static void method1(Class childConfig, String arg) {
...
}
public static void method2(Class childConfig, int arg1, String arg2) {
...
}
}
Now the callers would need to change
ChildA.method1("hello");
ChildA.method2(42, "world");
to
Base.method1(ChildA.class, "hello");
Base.method2(ChildA.class, 42, "world");
Another solution would be to replace static implementation with non-static, and use "regular" polymorphic behavior in conjunction with singletons created in derived classes:
class Base {
protected Base(Class childConfig) {
...
}
public void method1(String arg) {
...
}
public void method2(int arg1, String arg2) {
...
}
}
class ChildA extends Base {
private static final Base inst = new ChildA();
private ChildA() {
super(ChildA.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
class ChildB extends Base {
private static final Base inst = new ChildB();
private ChildB() {
super(ChildB.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
and call
ChildA.getInstance().method1("hello");
ChildA.getInstance().method2(42, "world");
There is only one Base.myType field shared amongst all accessors: Base, ChildA and ChildB. The following sequence of events could cause the failures you are seeing:
JUnit test invoking ChildA.methodOne() starts execution, causing the JVM classloader to load ChildA.class and execute its static initializer block, setting Base.myType to ChildType.ChildA,
JUnit test invoking ChildB.methodOne() starts execution, causing the JVM classloader to load ClassB.class and execute its static initializer block, setting Base.myType to ChildType.ChildB, then
JUnit test invoking ChildA.methodTwo() starts execution, not executing the ChildA static initializer block first as ChildA has already been loaded by the JVM classloader, resulting in the JUnit test failing because Base.myType (and thus ChildA.myType) presently equals ChildType.ChildB.
The basic design issue is that part of your code expects the child types to own the myType field but that field is in fact shared by all child types.
Please provide the order in which your JUnit tests are being run to verify the above theory. Thanks!
addendum: Thanks for clarifying in comments that you only have one JUnit test invoking just ChildA.methodTwo() which is only defined in Base, not ChildA. What is happening is likely the JVM deciding that ChildA need not be initialized just to call its parent Base class's methodTwo() method. #ShyJ provides a very nice explanation of this for parent and child static field access at https://stackoverflow.com/a/13475305/1840078. I believe that something similar is happening in your JUnit test.
addendum 2: Below is my code modeling and reproducing the described issue of myType having the value ChildType.Invalid during the JUnit test to the best of current understanding:
public enum ChildType {
Invalid, ChildA
}
public class Base {
protected static ChildType myType = ChildType.Invalid;
public static boolean methodTwo() {
return true;
}
}
public class ChildA extends Base {
static {
myType = ChildType.ChildA;
}
}
public class ChildATest {
#org.junit.Test
public void test() {
boolean result = ChildA.methodTwo();
System.out.println("result: " + result);
System.out.println("Base.myType: " + Base.myType);
}
}
Output of execution of ChildATest.test():
result: true
Base.myType: Invalid
I decided to try what #Arkdiy suggested and have pass-through methods in the child classes.
Let me reiterate: the code, as I had it, works perfectly when run as an application. Only when running via JUnit does it fail.
So now I have something similar to the below:
public class BaseClass {
protected static ChildType myType = ChildType.Invalid;
...
public static boolean methodTwoBase() {
...
}
}
public class ChildA extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildA;
return methodTwoBase();
}
}
public class ChildB extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildB;
return methodTwoBase();
}
}
Since I can't override static methods, the version of the method in the base class has a different signature (methodTwoBase() instead of methodTwo). I tried it as a regular application and in JUnit and it works both ways.
Kind of an interesting problem, and I blame JUnit. Thanks for all the input!

Deal with Final Class With Static Method

I have a method, I want to test. In there I call a static method of a final Hybris-class (Config.getParameter("aString")). I want to mock it, but I found out, you can't do that with Mockito. So what would be a good way to approach this? The thing is, I am thinking about refactoring. But I can't change the Config-class, since it is from Hybris.
How can I change my class I want to test, so that I can influence the Config.getParameter("aString") call?
Thanks!
There are two ways to do it:
1.Refactor your code and introduce ConfigWrapper (for example) interface:
public interface ConfigWrapper {
public String getParameter(String parameter);
public class ConfigWrapperImpl implements ConfigWrapper{
public String getParameter(String parameter){
return Config.getParameter(parameter);
}
}
Then you should refactor your code and replace Config.* usages by injecting ConfigWrapper. And when you write a test you can easily mock ConfigWrapper with mockito (cause you are using non-static method)
The second way is to use PowerMock instead of mockito:
PowerMock.mockStatic(ClassThatContainsStaticMethod.class)
for more info u can see: https://github.com/jayway/powermock/wiki/MockStatic
One solution is to create an interface whose method (or methods) match what you expect from that Config class. Then you can do the following:
create an implementation which uses that Config in production;
create a mock for your tests.
A simplified example using Java 8:
// The interface
public interface MyInterface
{
String getParameter(String paramName);
}
// Class using the interface
public final class MyClass
{
private final MyInterface intf;
// For testing...
public MyClass(final MyInterface intf)
{
this.intf = Objects.requireNonNull(intf);
}
// In production...
public MyClass()
{
this(Config::getParameter);
}
// etc
}
// Test class
#Test
public void whatever()
{
final MyInterface intf = mock(MyInterface.class);
// set up the mock, then...
final MyClass myClass = new MyClass(intf);
// test myClass
}
You could use besides Mockito, a tool call PowerMock which can be helpful in your use case.

Categories

Resources