I have an XYZ class which is autowired in ABC and in class MyClass I have a method name doSomething() inside that method I do ABC abc = new ABC(); Then I call abc.someMethod();
Please see code sample below :
Class ABC
public class ABC {
#Autowire
private XYZ xyz;
public void someMethod()
{
//Some stuff
xyz.someFunc();
}
}
Class MyCLass
public class MyCLass {
public void doSomething() {
ABC abc = new ABC();
abc.someMethod();
}
}
Need unit test doSomething() but I NPE as XYZ is null in ABC. How can I mock #Autowire in this case.
If you use constructor injection instead of field injection, you can create the mock and give it to the constructor of ABC:
public class ABC {
private final XYZ xyz;
public ABC(XYZ xyz) {
this.xyz = xyz;
}
public void someMethod()
{
//Some stuff
xyz.someFunc();
}
}
Then in your test, when you create the instance under test, you just create it and hand over the mock:
XYZ mock = mock(XYZ.class);
ABC underTest = new ABC(mock);
You can use the following testing capabilities in your test:
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
Provide a configuration and use it, for example:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = MyTest.MyTestConfiguration.class)
public class MyTest {
// xyz injected into ABC and MyTest for convenience.
#Autowired
private XYZ xyz;
#Test
public void myTest() {
// Some Stubbing...
when(xyz.trySomething()).thenReturn(true);
// Some verification.
new ABC().doSomething();
verify(xyz, times(1))
.trySomething();
}
// Note it is used in #ContextConfiguration
#Configuration
static class MyTestConfiguration {
#Bean
XYZ xyz() {
return mock(XYZ.class);
}
}
}
The documentation is a bit extensive, search for the mentioned annotations here https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#integration-testing
Related
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´m using google guice to inject this class example
class A {
String a;
}
Then is injected in my class B
class B {
#Inject A aInstance;
public void checkValue(){
System.out.println(aInstance.a);
}
}
Maybe using aspectJ, but what I would like is, that one test of mine, would get this A instance and would set the "a" string as "foo", before execute the test that cover the B class, so when the B class invoke checkValue this one would print "foo"
You mention the word test in your question - if you are writing a jUnit test for B you could perform the injection in an #Before clause, as demonstrated here.
private Injector injector;
#Before
public void init() throws Exception {
injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(A.class).to(MockedInstanceOfAWithValueFoo.class);
}
});
}
You could also call
bind(A.class).toInstance(new MockedInstanceOfAWithValueFoo());
If we assume that A has a constructor by which we can define A.a, the mocked instance could look like this:
public class MockedInstanceOfAWithValueFoo extends A{
public MockedInstanceOfAWithValueFoo() {
super("foo");
}
}
Again, you could make your mocked class accept the value of A.a through a constructor to make the creation of B (and the associated value of A.a) more dynamic.
With Mockito:
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MyTest {
#Mock
A mockA;
#InjectMocks
B mockB;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
mockA.a = "Foo";
//when(mockA.getA()).thenReturn("Foo"); //if you use getter
}
#Test
public void myTest() {
assertNotNull(mockA);
assertNotNull(mockA.a);
assertNotNull(mockB);
assertNotNull(mockB.ainstance);
mockB.checkValue();
}
}
I defined an EJB as follows:
#Stateless
#LocalBean
public class Foo {
#Inject
private Boo boo;
public void doSomething() {
boo.doOther();
}
}
And:
#Named
#RequestScope
public class Boo {
public void doOther() {
// I do, I do...
}
}
I would like to inject the Foo EJB into a JUnit test class:
import org.junit.*
public class FooTest {
#EJB
private Foo foo;
#Test
public void doSomethingTest() {
foo.doSomething();
assertTrue(true);
}
}
... But this code returns a NullPointerException.
What's wrong? How can I properly define that test by using Java EE CDI?
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(){
...
...
...
}
}
Hey I'm using Mockito and TestNG to write a unit test for a class that's making a lot of external calls to a service, I'm actually quite new to this hence I seem to be stuck with little documentation on the net for my exact problem.
my test looks like this basically
#Test
public class ClassToTestTest{
#Mock
private Object1 object1;
#Mock
private Object2 object2;
#InjectMocks
private ClassToTest classToTest;
public void test1(){
classToTest.methodToTest();
}
...
...
}
The actual class is as follows
import FinalClass;
public class ClassToTest{
private Object1 object1;
private Object2 object2;
public void methodToTest(){
object2 = FinalClass.getObject2();
...
...
}
...
...
}
I just need FinalClass.getObject2() to return the mock of Object2 That I've created in my Test, I know I can mock FinalClass using PowerMock, but I'm not quite getting how to inject it in the classToTest that I've created, so that when I run the classToTest.methodToTest() from my test object2 is initialized with my mocked implementation.
Thanks in Advance!
You're missing the annotation #PrepareForTest and the use of mockStatic() which are required when you wish to mock a final static class with PowerMockito. I think where you might be getting confused is that you're dealing with a final static class and not only a final class, so there are a few additional mock calls you need to be aware of.
Given these implementation classes
/*
The final static class that's giving you all the mocking grief
*/
public final class FinalStaticClass {
// this object instance "will not" be returned when we mock() the class
private static MyObject obj = new MyObject();
public static MyObject getMyObject() {
return obj;
}
}
/*
A simple value object used by MyClass
*/
public class MyObject {
}
/*
The class you wish to test
*/
public class MyClass {
private MyObject obj;
public void methodToTest() {
obj = FinalStaticClass.getMyObject();
// do something
}
public MyObject getMyObject() {
return obj;
}
}
Make sure you include powermock-mockito-1.4.10-full.jar in your project, then you can use this test class
import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import ...
#RunWith(PowerMockRunner.class)
#PrepareForTest(FinalStaticClass.class)
public class MyClassTest{
#Mock
MyObject expectedObject;
#InjectMocks
MyClass myClass = new MyClass();
#Test
public void test1(){
// mock all static methods
mockStatic(FinalStaticClass.class);
when(FinalStaticClass.getMyObject()).thenReturn(expectedObject);
// execute the method under test
myClass.methodToTest();
assertEquals(expectedObject, myClass.getMyObject());
}
}
You can see that expectedObject is a mock that you have created in the test and not the implementation returned from FinalStaticClass