How to use Mockito with HK2? - junit

I'm using HK2 for dependency injection and want to replace a Singleton Object with a Mockito-mock in the context of a JUnit-Test.
The simplest setting would be as follows:
import javax.inject.Inject;
import org.jvnet.hk2.annotations.Service;
#Service
public class A {
#Inject
private B b;
public String test() {
return b.toString();
}
}
#Service
public class B {
public String toString()
{
return "B";
}
}
whereas the JUnit-Test stub is as follows:
import static org.junit.Assert.*;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jvnet.hk2.testing.junit.HK2Runner;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class MockTest extends HK2Runner {
private B bMock = Mockito.mock(B.class);
#Inject
private A a;
#Test
public void test() {
Mockito.when(bMock.toString()).thenReturn("Mock");
assertEquals("Mocking worked", "Mock", a.test());
}
}
I want the Mock for B to be injected into A and not the real Object. How can I configure HK2 globally, such that for every instance of B the mock is used?
I already know that I could inject B locally into A by using injection via constructor.

Have you considered using a #Stub of B rather than a Mock?. To do that you can add #Contract onto the implementation of B:
#Service #Contract
public class B {
public String toString()
{
return "B";
}
}
and rather than using the mock use a #Stub:
public class MockTest extends HK2Runner {
#Inject
private A a;
#Test
public void test() {
assertEquals("Mocking worked", "Mock", a.test());
}
#Stub #Rank(1)
public static abstract class BStub extends B {
public String toString() {
return "Mock";
}
}
}
In order for this to work the hk2-metadata-generator should be in the classpath of your test during compilation so it can generate the stub. You put #Rank(1) on the stub to ensure it gets picked over the original B class.
Hope this helps!

Related

FasterXML ObjectMapper is not working with ExecutorService in a Junit test

It is a very strange issue. Removing the JSON in TestUtil or the executorService/submit will make the following code working:
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ATest {
#BeforeAll
public static void setup(TestInfo test) throws Exception {
}
#Test
void testThis(){
int numThreads = 1;
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
threadPool.submit(() -> {
TestUtils.doSomething();
});
}
}
Here is the class with the ObjectMapper>
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestUtils {
private static final ObjectMapper JSON;
static {
JSON = new ObjectMapper();
}
public static void doSomething() {
System.out.println("entered the method");
}
}
Currently, the method doSomething() would not be entered at all.
This issue will be resoved if we trigger the Junit test from Maven or if run it from a static main method.

PowerMock ExpectNew creating real objects instead of mocked Ones

public class PersistenceManager {
public boolean addUser(User user) {
UserPersistor userPersistor = new UserPersistor(user) {
#Override
void somemethod() {
// TODO Auto-generated method stub
}
};
userPersistor.addUser();
System.out.println("PersistenceManager added user ");
return true;
}
class User {
public String firstName;
public String lastName;
public User(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
}
abstract class UserPersistor {
public UserPersistor( ) {
}
public UserPersistor(User user) {
}
public void addUser() {
System.err.println("UserPersistor added user ");
}
abstract void somemethod();
}
}
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.expectNew;
import static org.powermock.api.easymock.PowerMock.expectLastCall;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest( PersistenceManager.class )
public class PersistenceManagerTest {
private User user = null;
#Before
public void before() throws Exception {
user = createMock(User.class);
UserPersistor userPersistor = createMock(UserPersistor.class);
userPersistor.addUser();
expectLastCall();
expectNew(UserPersistor.class, user).andReturn(userPersistor);
PowerMock.replayAll();
}
#Test
public void testaddUser() {
PersistenceManager tested = new PersistenceManager();
tested.addUser(user);
PowerMock.verifyAll();
}
}
Whats wrong with above code? I dont see mocked object for UserPersistor. Meaning, i dont want to see "UserPersistor added user " printed. It should not do anything. But it is printing it since real object of UserPersistor is created. I am facing this problem in my actual project, thought would simulate and try to solve in a much smaller context. But I am stumped.
That's because you are not expecting to instantiate UserPersistor but an anonymous inner class extending UserPersistor.
To do that you need to retrieve that class, mock it and expect it. PowerMock has a Whitebox class to do that. You are exposing the class implementation when using it. I would recommend that you refactor your code to inject the code instead. But if you really want to, you should write this:
#Before
public void before() throws Exception {
user = createMock(PersistenceManager.User.class);
Class<Object> clazz = Whitebox.getAnonymousInnerClassType(PersistenceManager.class, 1);
PersistenceManager.UserPersistor userPersistor = createMock(clazz);
userPersistor.addUser();
expectNew(clazz, user).andReturn(userPersistor);
PowerMock.replayAll();
}

Before Class Method of JUnit not called in correct order

I'm new to JUnit and was learning the various annotations. The code below however is giving me output that seems wrong
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
public class SampleTest {
#BeforeClass
public static void beforeClass() {
System.out.println("Before Class"); }
#AfterClass
public static void afterClass() {
System.out.println("After Class"); }
#Before
public void before() {
System.out.println("Before"); }
#After
public void after() {
System.out.println("After"); }
#Test
public void testAreFirstAndLastNCharactersTheSame() {
System.out.println("testAreFirstAndLastNCharactersTheSame");}
#Test
public void testTruncateAinFirstNPositions() {
System.out.println("testTruncateAinFirstNPositions"); }
}
The output I get is
Before
testTruncateAinFirstNPositions
After
Before
testAreFirstAndLastNCharactersTheSame
After
Before Class
After Class
This seems wrong as the "Before Class" print should be first. Am I doing something wrong? My Junit version is 4.12. I ran the above piece of code on Intellij.
The actual output screenshot is below

Not getting the answer if add method is static otherwise non-static add method is working

SimpleA.java class is target class. I have to mock getList method of SimpleB.java class if add method is non-static its working fine but it is showing problem with static add method
SimpleA.java
import java.util.ArrayList;
public class SimpleA {
private static SimpleB obj1 ;
public static int add(){
ArrayList<Integer> arr1 = obj1.getList1();
ArrayList<Integer> arr2 = obj1.getList2();
int res=0;
for(Integer val : arr1){
res+=val;
}
for(Integer val1 : arr2){
res+=val1;
}
return res;
}
}
SimpleB.java
import java.util.ArrayList;
import java.util.Iterator;
public class SimpleB {
public ArrayList<Integer> getList1(){
System.out.println("inside class SimpleB and getlist1");
ArrayList<Integer> lst1 = new ArrayList<Integer>();
lst1.add(10);
lst1.add(20);
return lst1;
}
public ArrayList<Integer> getList2(){
System.out.println("inside class SimpleB and getlist2");
ArrayList<Integer> lst2 = new ArrayList<Integer>();
lst2.add(30);
lst2.add(40);
return lst2;
}
}
SimpleATest.java
This is test class here I am testing for SimpleA.java class
import java.lang.reflect.Field;
import java.util.ArrayList;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
#RunWith(PowerMockRunner.class)
#PrepareForTest({SimpleA.class})
public class SimpleATest {
SimpleA simpleA1;
SimpleB mockSample;
#Before
public void setUp(){
ArrayList<Integer> lst = new ArrayList<Integer>();
lst.add(30);
lst.add(40);
lst.add(100);
simpleA1 = new SimpleA();
mockSample = PowerMock.createMock(SimpleB.class);
PowerMock.mockStatic(SimpleA.class);
EasyMock.expect(mockSample.getList1()).andReturn(lst);
EasyMock.expect(mockSample.getList2()).andReturn(lst);
PowerMock.replay(mockSample);
Whitebox.setInternalState(simpleA1,mockSample);
System.out.println("Init method is invoked");
}
#Test
public void testAdd(){
int res = simpleA1.add();
System.out.println("res = "+res);
}
#After
public void destroy(){
System.out.println("Destroy method is invoked");
}
}
I have seen this behavior in the past. The way around is to set first the default answer on the static methods and then fill in the behavior as such:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassWithStaticMethods.class)
public testClass{
#Test
public void testSomething(){
// this prepares the class; all static methods get a default return value (in this case type Object is returned and the default returned object is null)
PowerMockito.mockStatic(MyClassWithStaticMethods.class, new Answer<Object>()
{
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return null;
}
});
//Now the class is prepared, we can just change the behaviour of the static method in the way we would like.
String in = "example input string";
String out = "example output string";
// after preparing the class, you can override a specific static method. For this example we use the matchers, could also have used Matchers.any(String.class) or any other matcher combination as long as it maps on the method.
PowerMockito.when(MyClassWithStaticMethods.staticMethod(Matchers.eq(in))).thenReturn(out);
}
//..body
}

how to combine #RunWith with #RunWith(Parameterized.class)

I implemented a runner class A.class inherited from BlockJUnit4ClassRunner so that I can annotate tests with #RunWith(A.class). At the same time, sb. else annotate the tests with RunWith(Parameterized.class). It is obvious we cannot use two #RunWith at the same time.
How to solve this problem? or how to merge these two #RunWith?
I believe this does what you want:
package so.junit.runner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.model.InitializationError;
import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters;
import org.junit.runners.parameterized.ParametersRunnerFactory;
import org.junit.runners.parameterized.TestWithParameters;
import java.util.Arrays;
#RunWith(Parameterized.class)
#Parameterized.UseParametersRunnerFactory(CustomParameterizedTest.RunnerFactory.class)
public class CustomParameterizedTest {
#Parameterized.Parameters
public static Iterable<Integer> data() {
return Arrays.asList(new Integer[]{1, 2, 3});
}
private int i;
public CustomParameterizedTest(int i) {
this.i = i;
}
#Test
public void test() {
System.out.println(i);
}
public static class RunnerFactory implements ParametersRunnerFactory {
#Override
public org.junit.runner.Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
return new A(test);
}
}
public static class A extends BlockJUnit4ClassRunnerWithParameters {
private final Object[] parameters;
public A(TestWithParameters test) throws InitializationError {
super(test);
parameters = test.getParameters().toArray(new Object[test.getParameters().size()]);
}
#Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(parameters);
}
}
}
Based on the Javadocs in the JUnit Parameterized class, this is how they expect you to create a custom test runner that supports parameterization.
UPDATE
Updated to name the custom runner A