I have a class name LookupCode which is written as below.
class LookupCode {
public static LookUpCode getInstance() {
// This part will have more code for singleton.
return new LookUpCode();
}
public Map getCodeList(String code, String label) {
// return map.
}
}
My service class ABCService using LookupCode class of method getCodeList().
class ABCService {
LookupCode().getInstance().getCodeList("123", "456")`;
}
I wrote the test for ABCService by using Junit5 and Mockito. I am getting the exceptions from mockito saying getInstance() should return LookupCode`.
#Test
void test() {
try(MockedStatic<LookupCode> mockedStatic = Mockito.mockStaticLookupCode.class)) {
mockedStatic.when(() -> LookupCode().getInstance().getCodeList("123", "456")).thenReturn(buildMap());
}
}
You should first mock the result of the static method call .getInstance() and return a mocked instance of your LookukpCode class. Next, provide the stubbing on this mocked instance:
#Test
void test() {
LookupCode mockedLookupInstance = mock(LookupCode.class);
try(MockedStatic<LookupCode> mockedStatic = Mockito.mockStatic(LookupCode.class)) {
mockedStatic.when(LookupCode::getInstance).thenReturn(mockedLookupInstance);
when(mockedLookupInstance.getCodeList("123", "456").thenReturn(yourMap):
}
}
Not sure if deep stubbing works for mocking static methods with Mockito.
Related
I am trying to write a test with stubbing but mocking one of the methods does not happen as expected.
class A {
public static getInstance(){
return new A();
}
public String getConn(){
return "Hello";
}
}
class B {
public String createConn(){
A instance = A.getInstance();
return instance.getConn();
}
}
My Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class TestClassB{
#Spy
B classB = new B();
#Test
public void testConn(){
PowerMockito.mockStatic(A.class);
given(A.getConn()).thenReturn("Welcome");
assertEquals("Welcome", classB.createConn());
}
I want to create a test on Class B, createConn method, and when I get the connection, instead of "Hello", I want to receive "Welcome" using mockito?
I found the solution of the problem.
PowerMockito.mockStatic(A.class);
PropertyManager mock = PowerMockito.mock(A.class);
given(A.getInstance()).willReturn(mock);
given(mock.getConn()).willReturn("Welcome");
assertEquals("Welcome", classB.createConn());
Example of the problem:
class ToBeTested {
private MyResource myResource;
public toBeTested() {
this.myResource = getResource();
}
private MyResource getResource() {
//Creating My Resource using information form a DB
return new MyResource(...);
}
}
I would like to mock the getResource() so I would be able to provide a mock instance of MyResource. All the examples I found on how to mock a private method are based on first creating the ToBeTested instance and then replace the function but since it's being called from the constructor in my case it's to late.
Is it possible to mock the private function to all instances in advance of creating them?
Not directly but, you can suppress and then simulate with power mockito
#RunWith(PowerMockRunner.class)
#PrepareForTest(ToBeTested .class)
public class TestToBeTested{
#before
public void setup(){
suppress(method(ToBeTested.class, "getResource"));
}
#Test
public void testMethod(){
doAnswer(new Answer<Void>() {
#Override
public MyResource answer(InvocationOnMock invocation) throws Throwable {
return new MyResource();
}
}).when(ToBeTested.class, "getResource");
}
ToBeTested mock = mock(ToBeTested.class);
mock.myMethod();
//assert
}
I need to mock a static method only in one test case and wants it to return the original value in all the other testcases.
Class ClassWithStaticMethod
{
public static boolean aStaticMethod(String param)
{
//Some Code;
return value;
}
}
/// Test Class
#RunWith(PowerMockRunner.class)
Class ClassWithStaticMethodTest
{
#Test
testWhenNotMocked()
{
assertTrue(ClassWithStaticMethod.aStaticMethod("str1"));
}
#PrepareForTest({ClassWithStaticMethod.class})
#Test
testWhenMocked()
{
PowerMockito.mockStatic(ClassWithStaticMethod.class);
when(ClassWithStaticMethod.aStaticMethod("str1")).thenReturn(false);
assertFalse(ClassWithStaticMethod.aStaticMethod("str1"));
}
}
But the code is always returning false.
I have a class with two methods. I want to replace invocation of second method with expected result.
Here is my class under test
public class A {
public int methodOne() {
return methodTwo(1);
}
public int methodTwo(int param) {
// corresponding logic replaced for demo
throw new RuntimeException("Wrong invocation!");
}
}
And test
public class ATest {
#Test
public void test() {
final A a = spy(new A());
when(a.methodTwo(anyInt())).thenReturn(10);
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}
Why I'm get an exception when start the test?
Two things that will help you here. First, from the documentation it seems you need to use the do*() api with spy() objects. Second, to call the "real" method you need to declare it specifically using doCallRealMethod()
Here's the updated test that should work for you:
public class ATest {
#Test
public void test() {
final A a = spy(new A());
doReturn(10).when(a).methodTwo(anyInt());
doCallRealMethod().when(a).methodOne();
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}
I'm using EasyMock(version 2.4) and TestNG for writing UnitTest.
I have a following scenario and I cannot change the way class hierarchy is defined.
I'm testing ClassB which is extending ClassA.
ClassB look like this
public class ClassB extends ClassA {
public ClassB()
{
super("title");
}
#Override
public String getDisplayName()
{
return ClientMessages.getMessages("ClassB.title");
}
}
ClassA code
public abstract class ClassA {
private String title;
public ClassA(String title)
{
this.title = ClientMessages.getMessages(title);
}
public String getDisplayName()
{
return this.title;
}
}
ClientMessages class code
public class ClientMessages {
private static MessageResourse messageResourse;
public ClientMessages(MessageResourse messageResourse)
{
this.messageResourse = messageResourse;
}
public static String getMessages(String code)
{
return messageResourse.getMessage(code);
}
}
MessageResourse Class code
public class MessageResourse {
public String getMessage(String code)
{
return code;
}
}
Testing ClassB
import static org.easymock.classextension.EasyMock.createMock;
import org.easymock.classextension.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;
public class ClassBTest
{
private MessageResourse mockMessageResourse = createMock(MessageResourse.class);
private ClassB classToTest;
private ClientMessages clientMessages;
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.replay(mockMessageResourse);
}
}
When I'm running this this test I'm getting following exception:
java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")
While debugging what I found is, it's not considering the mock method call
mockMessageResourse.getMessage("ClassB.title") as it has been called from the construtor (ClassB object creation).
Can any one please help me how to test in this case.
Thanks.
You need to call EasyMock.replay(mock) before calling the method under test. After calling the method under test you can call EasyMock.verify(mock) to verify the mock is called.
Next you need to add another expect call with the "title" argument since you call it twice.
Code:
EasyMock.expect(mockMessageResourse.getMessage("title")).andReturn("title");
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.verify(mockMessageResourse);
In my case, it was caused by the omission of a return value specification (andReturn(...)).
http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html for more details.
This can have various causes (someMock is the name of your mocked Object in this answer).
On the one side it can be that you need to expect the call via
expect(someMock.someMethod(anyObject()).andReturn("some-object");
like in Reda's answer.
It can also be that you forgot to call replay(someMock) before you used the mock, like you can see in Julien Rentrop's answer.
A last thing that is possible that wasn't mentioned here is that you used the mock somewhere else before in a test and forgot to reset the mock via reset(someMock).
This can happen if you have multiple Unit Tests like this:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
This will fail on one test with the IllegalStateException, because the mock a was not reset before being used in the next test. To solve it you can do the following:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#After
public void tearDown() throws Exception {
reset(a); // reset the mock after each test
}
You should put your call to replay after the expect calls, and before you use your mock. In this case you should change your test to something like this:
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
}
For me, this exception was occurring because the method I was trying to stub was final (something I hadn't realized).
If you want to stub a final method you'll need to use Powermock.