I am writing unit test cases for following class which extends WCMUsePOJO. Now, this class is using a getSlingScriptHelper method shown below.
public class ConstantsServiceProvider extends WCMUsePojo {
private static final Logger logger = LoggerFactory.getLogger(ConstantsServiceProvider.class);
private String var1;
#Override
public void activate() throws Exception {
ConstantsService constantsService = getSlingScriptHelper().getService(ConstantsService.class);
if(constantsService != null) {
var1 = constantsService.getVar1();
}
}
public string getVar1() { return var1; }
}
The question is how do I mock getSlingScriptHelper method? Following is my unit test code.
public class ConstantsServiceProviderTest {
#Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
#Mock
public SlingScriptHelper scriptHelper;
public ConstantsServiceProviderTest() throws Exception {
}
#Before
public void setUp() throws Exception {
ConstantsService service = new ConstantsService();
scriptHelper = context.slingScriptHelper();
provider = new ConstantsServiceProvider();
provider.activate();
}
#Test
public void testGetvar1() throws Exception {
String testvar1 = "";
String var1 = provider.getVar1();
assertEquals(testvar1, var1);
}
}
The only thing that you should "have to"* mock is the SlingScriptHelper instance itself, so that it will mimic the dependency injection of the declared service.
Everything else (e.g. the Bindings instance) can be a concrete implementation, for example:
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.junit.Test;
import javax.script.Bindings;
import javax.script.SimpleBindings;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ConstantsServiceProviderTest {
private SlingScriptHelper mockSling = mock(SlingScriptHelper.class);
private ConstantsServiceProvider constantsServiceProvider = new ConstantsServiceProvider();
private Bindings bindings = new SimpleBindings();
#Test
public void testFoo() throws Exception {
//Arrange
final String expected = "Hello world";
final ConstantsService testConstantsService = new TestConstantsService(expected);
when(mockSling.getService(ConstantsService.class)).thenReturn(testConstantsService);
bindings.put(SlingBindings.SLING, mockSling);
//Act
constantsServiceProvider.init(bindings);
//Assert
final String actual = constantsServiceProvider.getVar1();
assertThat(actual, is(equalTo(expected)));
}
class TestConstantsService extends ConstantsService {
String var1 = "";
TestConstantsService(String var1) {
this.var1 = var1;
}
#Override
String getVar1() {
return var1;
}
}
}
The entry point here, as you said above, is via the init() method of the WCMUsePojo superclass (as this method is an implementation of the Use.class interface, this test structure also works for testing that via that interface, even if you don't use WCMUsePojo directly.)
*this could be any type of test-double, not necessarily a mock.
You shouldn't create a mock for ConstantsServiceProvider.class if you want to unit-test it. Instead, you should create mocks of its internal objects. So:
Create real instance of ConstantsServiceProvider with new
Mock objects that are returned by getSlingScriptHelper().getService(.) methods. Usually, dependencies are provided (injected) to classes by some container like Spring or simply provided by other classes of your app using setters. In both cases mocks creation is easy.
If your current implementation doesn't allow this - consider refactoring.
You are testing void activate() method which doesn't return anything. So, you should verify calling constantsService.getVar1() method.
I strongly advice you to study Vogella unit-testing tutorial
Here one of possible solution.
The main idea is to have a real object of your class but with overridden getSlingScriptHelper() to return mocked scriptHelper.
I mocked the ConstantsService as well but may be not needed, I don't know your code.
public class ConstantsServiceProviderTest {
#Mock
public SlingScriptHelper scriptHelper;
#Test
public void getVar1ReturnsActivatedValue() throws Exception {
// setup
final String expectedResult = "some value";
// Have a mocked ConstantsService, but if possible have a real instance.
final ConstantsService mockedConstantsService =
Mockito.mock(ConstantsService.class);
Mockito.when(
mockedConstantsService.getVar1())
.thenReturn(expectedResult);
Mockito.when(
scriptHelper.getService(ConstantsService.class))
.thenReturn(mockedConstantsService);
// Have a real instance of your class under testing but with overridden getSlingScriptHelper()
final ConstantsServiceProvider providerWithMockedHelper =
new ConstantsServiceProvider() {
#Override
SlingScriptHelper getSlingScriptHelper() {
return scriptHelper;
}
};
// when
String actualResult = providerWithMockedHelper.getVar1();
// then
assertEquals(expectedResult, actualResult);
}
}
Related
I want to mock the object inside the class wihtout using Powermock. How can I do it?
I tried using spy but it didn't work.
/** SOURCE CODE **/
abstract class Parent {
protected final Caller caller = new Caller();
public abstract void call(Connection, Integer);
}
class Child1 extends Parent {
#Override
public void call(Connection con, Integer id1) {
// some logic
caller.getSomething1(connection, id1);
}
}
class Child2 extends Parent {
#Override
public void call(Connection con, Integer id2) {
// some logic
caller.getSomething2(connection, id2);
}
}
class Activity {
#Inject
private MyConnection connection;
public Response process(Request r) {
Parent p = ChildFactory.getChild(r); // returns a child based on some logic related to p
p.call(connection, r.getId());
return new Response("SUCCESS");
}
}
/** TEST CODE **/
public class Test {
#InjectMocks
private Activity activity;
#Mock
private Connection connectionMock;
private Caller caller;
#Before
public void setup() throws Exception {
caller = Mockito.spy(Caller.class);
Mockito.doReturn(null).when(caller).getSomething1(Mockito.any(), Mockito.any());
Mockito.doReturn(null).when(caller).getSomething2(Mockito.any(), Mockito.any());
}
#Test
public void testProcess() {
Request r = new Request(1);
Response r = activity.process(r);
Assert.assertEquals(r.getResult(), "SUCCESS");
}
}
I want to mock the caller object created in Parent class. It is going to be consumed by every children. I am not bothered about the result of the calls so I want to mock all calls (i.e. getSomething1, getSomething2) of callers without use of PowerMock.
I tried using spy but it is not using the spied object and it is calling getSomething1 and getSomething2 methods.
You can use ReflectionTestUtils#setField
#Before
public void setup() throws Exception {
caller = Mockito.spy(Caller.class);
Mockito.doReturn(null).when(caller).getSomething1(Mockito.any(), Mockito.any());
Mockito.doReturn(null).when(caller).getSomething2(Mockito.any(), Mockito.any());
// ... obtain children here ...
ReflectionTestUtils.setField(child1, "caller", caller);
ReflectionTestUtils.setField(child2, "caller", caller);
}
Or better you don't instantiate Caller instance inside Child-classes but inject via constructor for example
I am trying to use PowerMockito to test a save method by verifying an internal audit() method call.
This internal call is made by auditor object which is being instantiated in an init() method of the class. As it is not injected I will not be able to mock it directly. When I used Mockito to verify it always said "There were zero interaction with the mock".
Question:How exactly do I test the save feature? Kindly help!
public class DaoImpl implements Dao{
private Auditor auditor;
#InjectValue
private ObjectLoader loader;
#InjectValue
private ConfigurationProvider confProvider;
#PostConstruct
public void init() {
//Mock this object instantiation and verify audit is called once
auditor = new SyncAuditor(confProvider.getClientConfiguration(), new EventRegProvider());
}
#Override
public void save(final AuditEvt auditEvt) {
final AuditedEvent auditedEvent = builder.build();
auditor.audit(auditedEvent);
}
Test :
#RunWith(PowerMockRunner.class)
#PrepareForTest({ DaoImplTest.class })
#PowerMockIgnore("javax.management.*")
public class DaoImplTest extends PowerMockito {
#InjectMocks
private DaoImpl dataAccess;
#Mock
private SynchAuditor auditorMock;
#Before
public void setUp() throws Exception {
loader = ObjectLoader.init("JUNIT");
loader.bind(ConfigurationProvider.class, configurationProviderMock);
dataAccess = loader.newInstance(DaoImpl.class);
}
#After
public void tearDown() {
loader.release(dataAccess);
ConnectionMgr.disconnect("JUNIT");
}
#Test
public void testSaveAuditEvent() throws Exception {
PowerMockito.whenNew(SynchAuditor.class).
withArguments(Matchers.any(ClientConfiguration.class), Matchers.any(EventRegProvider.class)).thenReturn(this.auditorMock);
final AuditEvent event = AuditEvent.from(null, "principal", UUID.randomUUID().toString(), "randomText",
new AuditEvtDefn((long) 522, "234242", "234242fdgd", true), SUCCESS, null, new GregorianCalendar());
dataAccess.save(event);
Mockito.verify(auditorMock, times(1)).audit(Matchers.any(AuditedEvent.class));
}
Even PowerMockito.verifyNew says there were zero interaction
PowerMockito.verifyNew(SynchronousAuditor.class,times(1)).withArguments(Matchers.any(AuditorClientConfiguration.class),Matchers.any(EventRegistrationProvider.class));
So, I figured out that java reflection will help in such a situation. You will have to get hold onto the real object and then set mocked object to it.
final Field privateAuditorField = DaoImpl.class.getDeclaredField("auditor");
privateAuditorField.setAccessible(true);
privateAuditorField.set(dataAccess, auditorMock);
Now verify will run sucessfully.
Mockito.verify(auditorMock, Mockito.times(1)).audit(Matchers.any(AuditedEvent.class));
I have a method whose JUnit test case I have to write. It just calls the main processing method of the project and does nothing else. Also, the main processing method also has return type as void.
How shall I test such a "method1"?
public void method1() {
obj1.mainProcessingMethod():
}
Given a class:
public class A {
private Obj obj1;
public void method1() {
obj1.mainProcessingMethod();
}
public void setObj1(Obj obj1) {
this.obj1 = obj1;
}
}
In test for this class, the only thing to test would be verification whether method obj1.mainProcessingMethod() was invoked exactly once.
You can achieve this with Mockito.
import org.junit.Test;
import org.mockito.Mockito;
public class ATest {
private Obj obj1 = Mockito.mock(Obj.class);
private A a = new A();
#Test
public void testMethod1() {
a.setObj1(obj1);
a.method1();
Mockito.verify(obj1).mainProcessingMethod();
}
}
Here you create a mock object for class Obj, inject it into instance of A, and later use mock object to check which method invocations it recorded.
Inside the test you need to verify that the method mainProcessingMethod(): is called on the object obj1.
you can use something like
Mockito.verify(yourMockObject);
I’m using Mockito 1.9.5. How do I mock what is coming back from a protected method? I have this protected method …
protected JSONObject myMethod(final String param1, final String param2)
{
…
}
However, when I attempt to do this in JUnit:
final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);
final String pararm1 = “param1”;
Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);
On the last line, I get a compilation error “The method ‘myMethod’ is not visible.” How do I use Mockito to mock protected methods? I’m open to upgrading my version if that’s the answer.
This is not an issue with Mockito, but with plain old java. From where you are calling the method, you don't have visibility. That is why it is a compile-time issue instead of a run-time issue.
A couple options:
declare your test in the same package as the mocked class
change the visibilty of the method if you can
create a local (inner) class that extends the mocked class, then mock this local class. Since the class would be local, you would have visibility to the method.
Responding to the request for a code sample of option 3 from John B's answer:
public class MyClass {
protected String protectedMethod() {
return "Can't touch this";
}
public String publicMethod() {
return protectedMethod();
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
class MyClassMock extends MyClass {
#Override
public String protectedMethod() {
return "You can see me now!";
}
}
#Mock
MyClassMock myClass = mock(MyClassMock.class);
#Test
public void myClassPublicMethodTest() {
when(myClass.publicMethod()).thenCallRealMethod();
when(myClass.protectedMethod()).thenReturn("jk!");
}
}
You can use Spring's ReflectionTestUtils to use your class as it is and without needing of change it just for tests or wrap it in another class.
public class MyService {
protected JSONObject myProtectedMethod(final String param1, final String param2) {
return new JSONObject();
}
public JSONObject myPublicMethod(final String param1) {
return new JSONObject();
}
}
And then in Test
#RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
#Mock
private MyService myService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
when(ReflectionTestUtils.invokeMethod(myService, "myProtectedMethod", anyString(), anyString())).thenReturn(mock(JSONObject.class));
}
}
Something like following worked for me, using doReturn() and Junit5's ReflectionSupport.
[Note: I tested on Mockito 3.12.4]
ReflectionSupport.invokeMethod(
mymock.getClass()
// .getSuperclass() // Uncomment this, if the protected method defined in the parent class.
.getDeclaredMethod("myMethod", String.class, String.class),
doReturn(myData).when(mymock),
param1,
param2);
John B is right, this is because the method you're trying to test is protected, it's not a problem with Mockito.
Another option on top of the ones he has listed would be to use reflection to gain access to the method. This will allow you to avoid changing the method you are testing, and avoid changing the pattern you use to write tests, and where you store these tests. I've had to do this myself for some tests where I was not allowed to change the existing code base which included a large number of private methods that needed to be unit tested.
These links explain Reflection and how to use it very well, so I will link to them rather than copy:
What is reflection and whit is it useful
How to test a class that has private methods, fields, or inner classes
WhiteBox.invokeMethod() can be handy.
public class Test extend TargetClass{
#Override
protected Object method(...) {
return [ValueYouWant];
}
}
In Spring, you can set it high high-priority like this:
#TestConfiguration
public class Config {
#Profile({"..."})
#Bean("...")
#Primary // <------ high-priority
public TargetClass TargetClass(){
return new TargetClass() {
#Override
protected WPayResponse validate(...) {
return null;
}
};
}
}
It is the same to override the origin bean.
I have simple code:
public interface AccountService {
public boolean verifyBalance(AccountInfo account);
}
public class MoneyTransferServiceBean implements MoneyTransferService {
private AccountService accountService;
class MoneyTransfer {
private TransferRequest request;
public MoneyTransfer(TransferRequest request) {
this.request = request;
}
private void verifySrcBalance() throws TransferException {
if (!accountService.verifyBalance("request")
throw new TransferException("LOW_BALANCE_ERROR_MESSAGE");
}
}
}
How Im make implement dummy for accountService.verifyBalance()
Im trying this:
private MoneyTransferServiceBean moneyTransferService;
AccountService mockedAccountService = mock(AccountService.class);
doReturn(true).when(mockedAccountService).verifyBalance("request");
MoneyTransfer moneyTransfer = moneyTransferService.new MoneyTransfer(transferRequest);
moneyTransfer.verifySrcBalance();
But this does not take effect.
generaly doX() methods are used for mocking exception throws and void methods.
Other use is mocked by when([method_call]).thenX();
First create mocks and put your mock into tested service with setters or Whitebox:
MoneyTransferServiceBean moneyTransferService = new MoneyTransferServiceBean();
AccountService mockedAccountService = mock(AccountService.class);
Whitebox.setInternalState(moneyTransferService , "accountService", mockedAccountService);
You should mock interaction with the mock like this:
when(mockedAccountService.verifyBalance(eq(accInfo)).thenReturn(true);
verify(mockedAccountService).verifyBalance(accInfo);
verifyNoMoreInteractions(mockedAccountService);
There are nice examples on Mockito site explaining it all.