I have a class, where i want to mock certain methods of the class and test the others. That is the only way i can verity and assert that it's working.
class UnderTest{
public void methodToTest(){
methodToCall1()
methodToCall2()
}
public void methodToCall1(){
}
public void methodToCall2(){
}
}
Now, since i want to test the first method, i want to create a partial mock of UnderTest so i can verify that those two methods were called.
How do i achieve this in Mockito?
Thanks for your help!
You mentioned you wanted to do two things:
1. Create real partial mocks
2. Verify method invocations
However, since your goal is to validate that methodToCall1() and methodToCall2() were actually invoked, all you need to do is spy on the real object. This can be accomplished with the following code block:
//Spy UnderTest and call methodToTest()
UnderTest mUnderTest = new UnderTest();
UnderTest spyUnderTest = Spy(mUnderTest);
spyUnderTest.methodToTest();
//Verify methodToCall1() and methodToCall2() were invoked
verify(spyUnderTest).methodToCall1();
verify(spyUnderTest).methodToCall2();
If one of the methods are not called, for example methodToCall1, an Exception will be thrown:
Exception in thread "main" Wanted but not invoked:
undertest.methodToCall1();
...
package foo;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Spy
private UnderTest underTest;
#Test
public void whenMethodToTestExecutedThenMethods1And2AreCalled() {
// Act
underTest.methodToTest();
// Assert
verify(underTest).methodToCall1();
verify(underTest).methodToCall2();
}
}
Related
I want to mock a static method using PowerMockito,
public class DepedencyService {
public static int getImportantValue() {
return -4;
}
}
public class Component {
public int componentMethod() {
return DepedencyService.getImportantValue();
}
}
but it is giving me an exception.
import static org.testng.Assert.assertEquals;
import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(DepedencyService.class)
public class ComponentTest {
#Test
public void testComponentMethod() {
Component c = new Component();
PowerMockito.mockStatic(DepedencyService.class);
EasyMock.expect(DepedencyService.getImportantValue()).andReturn(1);
assertEquals(1, c.componentMethod());
}
}
The exception :-
java.lang.IllegalStateException: no last call on a mock available at
org.easymock.EasyMock.getControlForLastCall(EasyMock.java:520) at
org.easymock.EasyMock.expect(EasyMock.java:498)
Can anyone please help me? Why is this failing? I am new to PowerMockito and does not know what to do here!
Your main problem is that you're writing STUPID code (like most of us did at the beginning) where you rather should write SOLID code.
Using Powermock is just a surrender to this bad design.
Yes, classes having only static methods are called utility classes.
But you should get over this misconception that classes providing common behavior should have (only) static methods.
As a rule of thumb there should be only one non private static method in your entire program, and this is main().
You appear to be mixing mocking frameworks.
You need to properly arrange the static dependencies before exercising the test
Since PowerMockito is used to mock the static class then you should use Mockito to arrange the expected behavior
For example
#RunWith(PowerMockRunner.class)
#PrepareForTest(DepedencyService.class)
public class ComponentTest {
#Test
public void testComponentMethod() {
//Arrange
int expected = 1;
PowerMockito.mockStatic(DepedencyService.class);
Mockito.when(DepedencyService.getImportantValue()).thenReturn(expected);
Component subject = new Component();
//Act
int actual = subject.componentMethod();
//Assert
assertEquals(expected, actual);
}
}
That said, I would advise not having your code tightly coupled to static dependencies. It makes for difficult to test code.
I am trying to Unit Test a class in Java.
Code for this class: ToBeTested
public class ToBeTested {
private Collaborator collaborator;
public ToBeTested() {
System.out.println("ToBeTested: Constructor");
}
public void start() {
System.out.println("ToBeTested: Start");
collaborator = new Collaborator();
}
}
This class ToBeTested depends on another class, Collaborator.
Code for class: Collaborator
public class Collaborator {
Collaborator() {
System.out.println("Collaborator: Constructor");
}
}
While testing the class ToBeTested, I want to stub instantiation of Collaborator. That's a dependency I want to mock and I don't want it's constructor to be called.
I'm using Junit (v4.12) and PowerMock (v1.6.1).
Code for Test Class: TestToBeTested
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.annotation.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ToBeTested.class, Collaborator.class})
public class TestToBeTested {
#Mock
private Collaborator collaborator;
private ToBeTested toBeTested;
#Before
public void setUp() throws Exception {
collaborator = createMock(Collaborator.class);
expectNew(collaborator.getClass()).andReturn(null);
toBeTested = new ToBeTested();
}
#Test
public void test() {
replayAll();
toBeTested.start();
verifyAll();
}
}
My understanding is that this will mock or stub out Collaborator and it's constructor should not be called. However, when I run the test, I notice that original constructor of Collaborator is called.
Output of test run:
ToBeTested: Constructor
ToBeTested: Start
Collaborator: Constructor
I'm very new to Java and Unit Testing in Java, so I apologize if I'm doing a very fundamental mistake here.
During my quest to find out the root cause, I have referred to following SO questions:
PowerMock's expectNew() isn't mocking a constructor as expected
PowerMock expectNew how to specify the type of the parameters
Not able to mock constructor using PowerMock
https://dzone.com/articles/using-powermock-mock
Thank you very much in advance for help/suggestions/feedback.
One possible reason that it might not be working could be this line:
expectNew(collaborator.getClass()).andReturn(null);
collaborator is a mocked instance which means it's "getClass()" method is going to return Collaborator$CGLIBMockedWithPowermock or something like that -- not the Collaborator class you want it to be. So you might get it to work simply by changing that line to:
expectNew(Collaborator.class).andReturn(null);
I'm trying to verify that the Collections.shuffle() method was called in one of my classes. I read through the (little) documentation on PowerMock with Mockito and read through the other SO questions that dealt with this issue and didn't get a resolution.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
PowerMockito.doCallRealMethod().when(Collections.class);
Collections.shuffle(Mockito.anyListOf(Something.class));
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}
public class ClassToTest {
private final List<Something> list;
// ...
public void doSomething() {
Collections.shuffle(list);
// do more stuff
}
}
Given the above code, I expect the unit test pass. However, the unit test fails as follows:
Wanted but not invoked java.util.Collections.shuffle([]);
Actually, there were zero interactions with this mock.
What am I doing wrong?
Thanks
EDIT:
As per the suggestion below I tried the following, and I get the same error.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}
This is a rather old question, but I'd still like to clarify that the accepted answer is in fact incorrect. By executing the following code,
PowerMockito.mockStatic(Collections.class);
Collections.shuffle(Mockito.anyListOf(Something.class));
all verifies will always pass afterwards:
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
even if you do not call test.doSomething(); the provided test in the answer will still pass. The correct way to test this is to actually check if the items in the List have been sorted correctly.
You can either mock/verify the java.util.Collections.shuffle([]) method or call the real implementation (with PowerMockito.doCallRealMethod()). But you can't do both.
If you remove
PowerMockito.doCallRealMethod().when(Collections.class);
the call will be verified and the test will pass.
https://powermock.googlecode.com/svn/docs/powermock-1.4.7/apidocs/org/powermock/api/mockito/PowerMockito.html#doCallRealMethod%28%29
This code works for me:
package test;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Collections.class)
public class MyTest {
#Test
public void testShuffle() {
PowerMockito.mockStatic(Collections.class);
/* PowerMockito.doCallRealMethod().when(Collections.class); remove this line */
Collections.shuffle(Mockito.anyListOf(Something.class));
ClassToTest test = new ClassToTest();
test.doSomething();
PowerMockito.verifyStatic(); // Verify shuffle was called exactly once
Collections.shuffle(Mockito.anyListOf(Something.class));
}
}
class ClassToTest {
private List<Something> list = new LinkedList<Something>();
// ...
public void doSomething() {
Collections.shuffle(list);
// do more stuff
}
}
class Something {
}
I'm using the Mockito framework to create Mock objects in my JUnit tests. Each mock knows what methods have been called on it, so during my tests I can write
verify(myMock, atLeastOnce()).myMethod();
I am wondering if this internal mock knowledge of what it has called will persist across my tests? If it does persist, then I could be getting false positives when using the same verify method in two tests.
A code example
#RunWith(MockitoJUnitRunner.class)
public class EmrActivitiesImplTest {
#Mock private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
// ..some logic
verify(myMock, atLeastOnce()).myMethod();
}
#Test
public void test2() {
// ..some other logic
verify(myMock, atLeastOnce()).myMethod();
}
}
Mock state is persisted - test2 will pass regardless, since test1's verify method passed
Mock state is reset - test2 will fail if myMock.myMethod() isn't called
JUnit creates a new instance of test class each time it runs a new test method and runs #Before method each time it creates a new test class. You can easily test it:
#Before
public void setup() {
System.out.println("setup");
when(myMock.myMethod()).thenReturn("hello");
}
And MockitoJUnitRunner will create a new MyMock mock instance for every test method.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
#RunWith(MockitoJUnitRunner.class)
public class sandbox {
#Mock
private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
#Test
public void test2() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
}
This passes. If the state persisted then the second test would fail. If you debug it you would see that you get a new instance of the mocked object for each test.
If you just initialize the Mock objects in your setup, then inside each test you can provide different functionality. You can initialize it once and change how they act/expect per test after that.
I am using Mockito for unit testing. I am wondering if its possible to send Parametrized input parameters with as in Junit testing
e.g
#InjectMocks
MockClass mockClass = new MockClass();
#Test
public void mockTestMethod()
{
mockClass.testMethod(stringInput);
// here I want to pass a list of String inputs
// this is possible in Junit through Parameterized.class..
// wondering if its can be done in Mockito
}
In JUnit, Parameterized tests use a special runner that ensure that the test is instantiated multiple times, so each test method is called multiple times. Mockito is a tool for writing specific unit tests, so there is no built-in ability to run the same test multiple times with different Mockito expectations.
If you want your test conditions to change, your best bet is to do one of the following:
Parameterize your test using JUnit, with a parameter for the mock inputs you want;
Run a loop of different parameters in your test, which unfortunately avoids the "test one thing per method" philosophy
Extract a method that actually performs the test, and create a new #Test method for each mock you want.
Note that there's no prohibition on using mock objects as #Parameterized test parameters. If you're looking to parameterize based on mocks, you can do that, possibly creating the mock and setting the expectations in a static method on the test.
Note about runners: This Parameterized test runner conflicts with Mockito's MockitoJUnitRunner: Each test class can only have one runner. You'll want to switch to #Before and #After methods or a Mockito JUnit4 rule for your setup, if you use them both.
As an example, compressed from a different answer that explains more about Parameterized runners versus JUnit rules and lifting from the JUnit4 Parameterized Test doc page and MockitoRule doc page:
#RunWith(Parameterized.class)
public class YourComponentTest {
#Rule public MockitoRule rule = MockitoJUnit.rule();
#Mock YourDep mockYourDep;
#Parameters public static Collection<Object[]> data() { /* Return the values */ }
public YourComponentTest(Parameter parameter) { /* Save the parameter to a field */ }
#Test public void test() { /* Use the field value in assertions */ }
}
If you are stuck with an older version of mockito where MockitoRule isn't available, the other possibility is to initialize the mocks explicitely with MockitoAnnotations.initMocks:
#RunWith(Parameterized.class)
public class YourComponentTest {
#Mock YourDep mockYourDep;
#Parameter
public Parameter parameter;
#Parameters public static Collection<Object[]> data() { /* Return the values */ }
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test public void test() { /* Use the field value in assertions */ }
}
You can use the JUnitParamsRunner. Here's how I do it:
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Arrays;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
#RunWith(value = JUnitParamsRunner.class)
public class ParameterizedMockitoTest {
#InjectMocks
private SomeService someService;
#Mock
private SomeOtherService someOtherService;
#Before
public void setup() {
initMocks(this);
}
#Test
#Parameters(method = "getParameters")
public void testWithParameters(Boolean parameter, Boolean expected) throws Exception {
when(someOtherService.getSomething()).thenReturn(new Something());
Boolean testObject = someService.getTestObject(parameter);
assertThat(testObject, is(expected));
}
#Test
public void testSomeBasicStuffWithoutParameters() {
int i = 0;
assertThat(i, is(0));
}
public Iterable getParameters() {
return Arrays.asList(new Object[][]{
{Boolean.TRUE, Boolean.TRUE},
{Boolean.FALSE, Boolean.FALSE},
});
}
}
What solved it for me was:
Class level annotation of #ExtendWith(MockitoExtension.class)
Annotate each mock object with #Mock
#InjectMocks on the test class. Or a setup method annotated with #BeforeEach where you initialise the class to be tested.
if you need the #test annotation, make sure you import org.junit.jupiter.api.Test. org.junit.test will not work!
I'm using mockito version 4.