I have code, which is using old version of JMockit library.
#MockClass(realClass = SomeClass.class)
public class MockSomeClass {
public SomeClass it;
#Mock
public void $init(DataSource dataSource) {
Deencapsulation.setField(it, new MockDataSource());
}
}
How should I change #MockClass annotation?
public class MockSomeClass extends Mockup<SomeClass>{
public SomeClass it;
#Mock
public void $init(DataSource dataSource) {
Deencapsulation.setField(it, new MockDataSource());
}
}
Related
I am trying to write test case for the below class where everytime myConfig instance is coming as null. Is there any way to pass the autowired instance.
public class MyClass {
#Autowired
MyConfig myConfig ;
public Properties getUnAckMessage(String queueName) {
Properties prop=new Properties()
URL url = new URL(StringUtils.join(myConfig.getQueueHost(),
myConfig.getQueueURL(),myConfig.getQueueVm(),queueName));
return prop;
}
public Properties request(String queue) {
return getUnAckMessage(queue);
}
}
public class Main {
public void method() {
MyClass myClass=new MyClass();
myClass.getUnAckMessage("test");
}
}
Test case
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#MockBean
MyConfig myConfigReader;
#Test
public void testMyClass() {
MyClass propertiesExchangeManager1 = new MyClass ();
propertiesExchangeManager1.request("test");
}
}
You must activate Spring for your test if you want Spring to autowire. For example:
#RunWith(SpringRunner.class)
public class Test {
#Autowired private MyClass myClass
#Test
public void test() {
///...
}
}
If you instantiate the class MyClass by yourself, Spring cannot inject the needed classes. You should modify your test like this:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#MockBean
MyConfig myConfigReader;
#Autowired
MyClass propertiesExchangeManager1;
#Test
public void testMyClass() {
propertiesExchangeManager1.request("test");
}
}
Say I have the following
public abstract class MyClass {
#Resource
protected MyService myService;
doSomething() {
return myService.doSomething();
}
}
public class MyServiceV1 implements MyService {}
public class MyServiceV2 implements MyService {}
public class MyClassV1 extends MyClass {
//WANT TO USE MyServiceV1 implementation
}
public class MyClassV2 extends MyClass {
//WANT TO USE MyServiceV2 implementation
}
I am unable to specify the service implementation that I want to use in each subclass. I have considered using #Qualifier but I would have to re-declare the property in each child class and use it there, and hope that it overrides the parent.
The purpose of these classes is to provide two versions of an API at the same time. So both versions will be active simultaneously.
It does feel partially that this is an anti pattern in terms of how spring is meant to inject beans, so I am open to other approaches.
I think you can try to use Constructor injection to set a particular service in your classes. Smth like this:
public abstract class MyClass {
protected MyService myService;
doSomething() {
return myService.doSomething();
}
}
class MyClassV1 extends MyClass {
MyClassV1(MyService myService) {
this.myService = myService;
}
}
class MyClassV2 extends MyClass {
MyClassV2(MyService myService) {
this.myService = myService;
}
}
#Bean
MyClassV1 myClassV1() {
return new MyClassV1(myServiceV1());
}
#Bean
MyClassV1 myClassV2() {
return new MyClassV2(myServiceV2());
}
#Bean
MyServiceV1 myServiceV1() {
return new MyServiceV1();
}
#Bean
MyServiceV2 myServiceV2() {
return new MyServiceV2();
}
or setter injection:
public abstract class MyClass {
private MyService myService;
public void setMyService(MyService myService) {
this.myService = myService;
}
}
#Component
public class MyClass1 extends MyClass {
#Autowired #Qualifier("myService1")
#Override
public void setMyService(MyService myService) {
super.setMyService(myService);
}
}
#Component
public class MyClass2 extends MyClass {
#Autowired #Qualifier("myService2")
#Override
public void setMyService(MyService myService) {
super.setMyService(myService);
}
}
I am having some issues with a jukito unit test. I can't seem to mock Provider. Examples:.
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
#Singleton
public class ServiceClass1 {
#Inject
Provider<ConnectionClass> provider;
public void method1() {
Object o = provider.get().getO(); //during mainTest, provider is null and I get Nullpointer
}
}
#Singleton
public class ConnectionClass {
public Object getO() {
//this is not relevant
}
}
public class ConfigurationModule extends AbstractModule {
bind(ServiceClass1.class).in(Singleton.class);
bind(ConnectionClass.class).in(Singleton.class);
}
#RunWith(JukitoRunner.class)
public class ServiceClass1Test {
#InjectMocks
ServiceClass1 service;
#Mock
Provider<ConnectionClass> connectionClassProvider;
#Mock
ConnectionClass connectionClass;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(connectionClassProvider.get()).thenReturn(connectionClass);
}
#Test
public void mainTest() {
service.method1();
}
}
I expect to get a mocked connection class, but instead provider returns null. I tried binding connectionClass to TestSingleton, but that does not help. Inside test class:
public static class Module extends JukitoModule {
#Override
protected void configureTest() {
bindMock(ConnectionClass.class).in(TestSingleton.class);
}
}
If anyone has some suggestions for me, I would greatly appreciate it.
Using constructor injection instead of field injection:
#Singleton
public class ServiceClass1 {
Provider<ConnectionClass> provider;
#Inject
public ServiceClass1(Provider<ConnectionClass> provider) {
this.provider = provider;
}
}
and dropping InjectMocks:
#Mock
Provider<ConnectionClass> provider;
ServiceClass1 serviceClass1;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
serviceClass1 = new ServiceClass1(provider);
}
makes everything work. Can InjectMocks be the cause of this? Anyway, I guess this will do for now.
I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.
public class MyClass{
private MyObj obj;
MyClass (String profile)
{
//some 3rd party library call
obj = thridPartyLib.someMethod(profile);
}
public String someMethod(){
return obj.someExternalCall();
}
}
Class which I want to test
public class ClassTobeTested{
public void execute(){
//some code
// ......
MyClass myClass = new MyClass(profile);
myclass.someMethod();
}
}
What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = new ClassTobeTested();
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute(){
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work
#RunWith(PowerMockRunner.class)
#PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = spy(new ClassTobeTested());
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute() throws Exception {
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj. For example:
class MyObjFactory {
MyObj create(String profile) {
return new MyClass(profile);
}
}
then
public class ClassTobeTested {
private final MyObjFactory factory;
public ClassTobeTested(MyObjFactory factory) {
this.factory = factory;
}
public void execute(){
//some code
// ......
// MyClass myClass = new MyClass(profile);
MyClass myClass = factory.create(profile);
myclass.someMethod();
}
}
so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.
I have the following class:
public class MyClass {
private Apple apple;
public void myMethod() {
apple = AppleFactory.createInstance(someStringVariable);
....
....
....
}
}
And the Test class:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#InjectMocks
MyClass myClass;
#Test
public void myMethod(){
...
...
...
}
}
How could I inject an Apple instance as a mock in MyClass?
You have 3 possibilities to solve this:
Abstract factory: Instead of using a static method, use a concrete factory class:
public abstract class AppleFactory {
public Apple createInstance(final String str);
}
public class AppleFactoryImpl implements AppleFactory {
public Apple createInstance(final String str) { // Implementation }
}
In your test class, mock the factory:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private AppleFactory appleFactoryMock;
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Before
public void setup() {
when(appleFactoryMock.createInstance(Matchers.anyString()).thenReturn(appleMock);
}
#Test
public void myMethod(){
...
...
...
}
}
PowerMock: Use PowerMock to create a mock of a static method. Look at my answer to a relevant question to see how it's done.
Testable class: Make the Apple creation wrapped in a protected method and create a test class that overrides it:
public class MyClass {
private Apple apple;
public void myMethod() {
apple = createApple();
....
....
....
}
protected Apple createApple() {
return AppleFactory.createInstance(someStringVariable);
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Test
public void myMethod(){
...
...
...
}
private class TestableMyClass extends MyClass {
#Override
public void createApple() {
return appleMock;
}
}
}
Of course, in your test class you should test TestableMyClass and not MyClass.
I'll tell you my opinion on each of the methods:
The abstract factory method is the best one - This is a clear design that hides the implementation details
The testable class - Is the second option which requires minimum changes
The PowerMock option is my least favorite - Instead of going for a better design, you ignore and hide your problem. But that's still a valid option.
In addition of the solution proposed by Avi, you can choose a fourth possibility:
Inject into Factory:
This is, for me, the best option when you already have code to refacrot. With this solution you don't have to change porduction code but only factory class and test.
public class AppleFactory
{
private static Apple _injectedApple;
public static createInstance(String str)
{
if (_injectedApple != null)
{
var currentApple = _injectedApple;
_injectedApple = null;
return currentApple;
}
//standard implementation
}
public static setInjectedApple(Apple apple)
{
_injectedApple = apple;
}
}
Now you can use your static factory simply:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Before
public void setup() {
AppleFactory.setInjectedApple(appleMock);
}
#Test
public void myMethod(){
...
...
...
}
}