I m using mockito for junit. I have doubt while creating mock of object.
I have class called DBConnect. Where I need database properties like dbname, credentials etc.
This class is used by PatientDetails. Now when I am writing junit for PatientDetails. So I am using following code.
#RunWith(MockitoJUnitRunner.class)
public class PatientDetailsTest {
#Mock
DBConnect dbConnect
#Before
public void setUp()
{
PatientDetails testClass = new PatientDetails();
testClass.setDBConnect(dbConnect);
}
}
I can not get correct result with this.
You code seems fine to me. I've extended it slightly to include a test, so that it can be run. This works fine:
#RunWith(MockitoJUnitRunner.class)
public class PatientDetailsTest {
#Mock
DBConnect dbConnect;
#Before
public void setUp() {
when(dbConnect.sayHello()).thenReturn("works for me");
PatientDetails testClass = new PatientDetails();
testClass.setDBConnect(dbConnect);
}
#Test
public void testname() throws Exception {
System.out.println("foo");
}
private static interface DBConnect {
String sayHello();
}
private static class PatientDetails {
public void setDBConnect(DBConnect dbConnect) {
System.out.println(dbConnect.sayHello());
}
}
}
Output:
works for me
foo
Related
My following Unit test is failing.
I'm getting an error The class com.xyz.sys.PluginManager not prepared for test.
// #RunWith(PowerMockRunner.class)
#RunWith(GlideUiRunner.class)
public class TestClass extends BaseITClass {
private static final String PLUGIN_MESSAGE = "texttt";
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
// PowerMockito.mockStatic(RecordCache.class);
}
#Test
public void testUpgradeMonitorDontShowAtfPluginWarningMessage() {
open(UPGRADE_PAGE);
String actualMsg = findElement(By.xpath("//div[#ng-if='divElementName']")).getText();
PowerMockito.mockStatic(PluginManager.class);
PowerMockito.when(PluginManager.isActive("pluginName")).thenReturn(true);
Assert.assertFalse(actualMsg.contains(PLUGIN_MESSAGE));
}
}
Any suggestions where the issue is?
Note: I need to use GlideUiRunner.class.. Can't remove that.
I'm trying to write a unittest (test_myMethod) for one of my methods (myMethod) but I can't seem to get it to work. I get a NullPointer exception error with the code below. In my test it seems that the line myClass.otherMethod("hostName") in the unittest evaluates to Null so it can't do .getOSRevision(). Anyone know how I can get my unittest to pass?
MyClass.java
public class MyClass {
public String myMethod(final String hostname) {
return otherMethod(hostname).getOSRevision();
}
public OtherMethod otherMethod(final String hostname) {
OtherMethod response = myClient.newMyMethodRevisionCall().call(
someObject.builder()
.withHostName(hostname)
.build()
);
return response;
}
}
MyClassTest.java
public class MyClassTest {
#Mock
private MyClient myClient;
#Mock
private MyMethodRevisionCall myMethodRevisionCall;
#Mock
private OtherMethod otherMethod;
private MyClass myClass;
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
when(myClient.newMyMethodRevisionCall()).thenReturn(myMethodRevisionCall);
myClass = new MyClass(myClient);
}
// My failing unittest attempt
#Test
public void test_myMethod() {
when(myClass.otherMethod("hostName")
.getOSRevision()) //java.lang.NullPointerException happens on this line.
.thenReturn("TestString");
final String result = myClass.myMethod("TestString");
verify(myMethodRevisionCall, times(1)
}
}
You cannot use Mockito.when() on classes that are not mocked by Mockito. MyClass is not a mock. Instead you create an actual instance of it. Therefore, you need to actually run the code and not mock it. However, all dependencies of your class under test (MyClient in your case) you can mock.
This is a working example:
public class MyClass {
private MyClient myClient;
public MyClass(MyClient myClient) {
this.myClient = myClient;
}
public String myMethod(final String hostname) {
return otherMethod(hostname).getOSRevision();
}
public OtherMethod otherMethod(final String hostname) {
return myClient.newMyMethodRevisionCall().call(new SomeObject(hostname));
}
}
class MyClassTest {
private MyClient myClient;
private MyClass myClass;
#BeforeEach
void setUp() {
myClient = mock(MyClient.class);
myClass = new MyClass(myClient);
}
#Test
public void test_myMethod() {
MyMethodRevisionCall myMethodRevisionCall = mock(MyMethodRevisionCall.class);
OtherMethod otherMethod = mock(OtherMethod.class);
when(myClient.newMyMethodRevisionCall()).thenReturn(myMethodRevisionCall);
when(myMethodRevisionCall.call(any())).thenReturn(otherMethod);
when(otherMethod.getOSRevision()).thenReturn("revision");
final String result = myClass.myMethod("TestString");
assertEquals("revision", result);
verify(myMethodRevisionCall, times(1));
}
}
I have a class name ServiceLocator
public class ServiceLocator implements ApplicationContextAware {
private transient ApplicationContext _applicationContext;
private static ServiceLocator _instance = new ServiceLocator();
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
_instance._applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return _instance._applicationContext;
}
public static Object findService(String serviceName) {
return _instance._applicationContext.getBean(serviceName);
}
}
I am trying to use that class to find Service into Approver class methods
public class ApproverService extends AbstractDataService implements IApproverService {
public void updateCompletedInboxStatus(String status) {
IInboxService inboxService = (IInboxService)ServiceLocator.findService("inboxService");
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
With that code i am trying to write Junit with PowerMockRunner
#RunWith(PowerMockRunner.class)
#PrepareForTest({ApproverService.class})
public class ApproverServiceTest {
#InjectMocks
ApproverService approverService;
#Mock
IInboxService inboxService;
#Mock
ServiceLocator serviceLocator;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
RequestAccessHeader reqHdr = new RequestAccessHeader();
reqHdr.setRequestStatus(AccessConstants.REQ_STATUS_HOLD_INT);
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(serviceLocator.findService("inboxService")).thenReturn(inboxService);
approverService.updateCompletedInboxStatus(status);
}
}
But I am getting null pointer
java.lang.NullPointerException
at com.alnt.fabric.common.ServiceLocator.findService(ServiceLocator.java:25)
at com.alnt.access.approver.service.ApproverServiceTest.updateCompletedInboxStatus(ApproverServiceTest.java:80)
Please help me to find the solution for that issue.
The static method is obviously not mocked.
The problem is most probably because you haven't add the to-be-mocked class in #PrepareForTest
Change it to #PrepareForTest({ApproverService.class, ServiceLocator.class})
Off-topics:
Although it compiles, calling static method by instance reference is not a good practice. Therefore the line should be when(ServiceLocator.findService(...)).thenReturn(inboxService).
Another problem is, you tried to use Singleton pattern but in wrong way. A singleton is suppose to return you an instance so the caller can call its instance method. Your findService is preferably an instance method and to be called as ServiceLocator.getInstance().findService(...). To further improve, unless you really need it to be a singleton, you should make it a normal object instance and inject to objects that need it (given you are already using Spring, I see no reason making a Singleton)
The setup for the static method is not mocked correctly
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServiceLocator.class}) //Prepare static class for mock
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(ServiceLocator.findService("inboxService")) //<-- NOTE static call
.thenReturn(inboxService);
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}
Reference Mocking Static Method
The subject under test should actually be refactored to avoid the service locator anit-pattern / code smell and should follow explicit dependency principle via constructor injection.
public class ApproverService extends AbstractDataService implements IApproverService {
private IInboxService inboxService;
#Autowired
public ApproverService(IInboxService inboxService){
this.inboxService = inboxService;
}
public void updateCompletedInboxStatus(String status) {
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
That way the subject class is genuine about what it needs to perform its function correctly,
And the test can then be refactored accordingly
#RunWith(PowerMockRunner.class)
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}
I am trying to unit test a method, which has different branches depending upon the value of an object that is created inside it. The below code demonstrates it.
public class AClass {
public void method2() {
//Some code goes here
}
public void method1(BClass bObject) {
C_Class cObject = bObject.someMethodThatReturnsC();
if(cObject != null) {
method2();
method2();
}
}}
Below is the TestClass:
public class AClassTest {
#InjectMocks
AClass AClassSpy;
#Mock
BClass b_objectMock;
#Mock
C_Class c_objectMock;
#BeforeMethod
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
public void method1Test () {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC());
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2).method2();
}
}
However, it always FAILS, since the c_objectMock is always null. What do I do to tell Mockito to not to return a null object?
It works good, just use #Before annotation from junit, not #BeforeMethod, and mark your test method like #Test and remove second bracket from
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC())<-this one;
and add bracket at verify:
verify(AClassSpy, times(2)<-here.method2();
And just take care of your code!
This should work:
public class AClassTest {
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Before
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
Instead of before method you can use annotation #RunWith. It looks clearly:
#RunWith(MockitoJUnitRunner.class)
public class AClassTest {
#Spy
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
You are having this behaviour because you are not mocking property the call to someMethodThatReturnsC.
It should be:
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
I have this code in my Subject Under Test:
public class Widget {
private Set<Thing> things;
public Set<Thing> getThings() { return things; }
public void setThings(Set<Thing> things) { this.things = things; }
public void performAction(PerformingVisitor performer) {
for (Thing thing: getThings())
{
thing.perform(performer);
}
}
}
My JUnit/Mockito test looks like:
#RunWith(MockitoJUnitRunner.class)
public class WidgetTest {
#Mock private PerformingVisitor performer;
#Mock private Thing thing;
#InjectMocks private Widget widget;
#Before
public void setUp() throws Exception {
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldPerformThing() {
Mockito.when(thing.perform(Mockito.any(PerformingVisitor.class))).thenReturn(true);
widget.performAction(performer);
Mockito.verify(thing).perform(Mockito.any(PerformingVisitor.class));
}
}
However, this gives me the error:
Wanted but not invoked:
thing.perform(<any>);
-> at com.myclass.ThingTest.shouldPerformThing(WidgetTest.java:132)
I've verified that the code enters the for loop and should be calling the actual thing.perform(performer); line, but my mock does not seem to be recording a call.
I think you need initMocks before the mock injection.
Could you try to change your setUp method for this:
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
}
Hope it works
From the MockitoJUnitRunner javadoc:
Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary.
So, if you remove
MockitoAnnotations.initMocks(this)
from your setUp method, the test pass.