Mockito verify order / sequence of method calls - java

Is there a way to verify if a methodOne is called before methodTwo in Mockito?
public class ServiceClassA {
public void methodOne(){}
}
public class ServiceClassB {
public void methodTwo(){}
}
public class TestClass {
public void method(){
ServiceClassA serviceA = new ServiceClassA();
ServiceClassB serviceB = new ServiceClassB();
serviceA.methodOne();
serviceB.methodTwo();
}
}

InOrder helps you to do that.
ServiceClassA firstMock = mock(ServiceClassA.class);
ServiceClassB secondMock = mock(ServiceClassB.class);
Mockito.doNothing().when(firstMock).methodOne();
Mockito.doNothing().when(secondMock).methodTwo();
//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).methodOne();
inOrder.verify(secondMock).methodTwo();

Note that you can also use the InOrder class to verify that various methods are called in order on a single mock, not just on two or more mocks.
Suppose I have two classes Foo and Bar:
public class Foo {
public void first() {}
public void second() {}
}
public class Bar {
public void firstThenSecond(Foo foo) {
foo.first();
foo.second();
}
}
I can then add a test class to test that Bar's firstThenSecond() method actually calls first(), then second(), and not second(), then first(). See the following test code:
public class BarTest {
#Test
public void testFirstThenSecond() {
Bar bar = new Bar();
Foo mockFoo = Mockito.mock(Foo.class);
bar.firstThenSecond(mockFoo);
InOrder orderVerifier = Mockito.inOrder(mockFoo);
// These lines will PASS
orderVerifier.verify(mockFoo).first();
orderVerifier.verify(mockFoo).second();
// These lines will FAIL
// orderVerifier.verify(mockFoo).second();
// orderVerifier.verify(mockFoo).first();
}
}

Yes, this is described in the documentation. You have to use the InOrder class.
Example (assuming two mocks already created):
InOrder inOrder = inOrder(serviceAMock, serviceBMock);
inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();

For Kotlin users, you can go this way:
class MyTrackerTest {
private val trackEventUseCase: TrackEventUseCase = mock()
private val sut = MyTracker(trackEventUseCase)
#Test
fun `trackSomething SHOULD invoke tracker use case twice with correct event names WHEN called`() {
sut.trackSomething()
trackEventUseCase.inOrder {
verify().invoke("Is it August?")
verify().invoke("No!")
}
}
}

With BDD it's
#Test
public void testOrderWithBDD() {
// Given
ServiceClassA firstMock = mock(ServiceClassA.class);
ServiceClassB secondMock = mock(ServiceClassB.class);
//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);
willDoNothing().given(firstMock).methodOne();
willDoNothing().given(secondMock).methodTwo();
// When
firstMock.methodOne();
secondMock.methodTwo();
// Then
then(firstMock).should(inOrder).methodOne();
then(secondMock).should(inOrder).methodTwo();
}

Related

Why Mockito is calling real method?

I have a class Service that calls a method of singleton class. I would like to mock a saveContract method calls.
public class Service {
public Contract save(Contract contract) {
Contract result;
...
result = ContractDao.getInstance().saveContract(contract);
...
return result;
}
}
I modified Service class like this (added a field and a constructor, for testing purposes only):
public class Service {
private final ContractDao contractDao;
public Service() {
this(ContractDao.getInstance());
}
public Service(final ContractDao contractDao) {
this.contractDao = contractDao;
}
public Contract save(Contract contract) {...}
}
And my test class is:
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Mock
ContractDAO contractDaoMock;
private Service service;
#BeforeEach
public void setup() {
service = new Service(contractDaoMock);
}
#Test
void saveContractTest() {
Contract changedContract = new Contract(...);
when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
Contract givenContract = new Contract(...);
Contract actualContract = service.save(givenContract);
//Assertions
...
}
}
Add mockito-inline dependency and use the MockedStatic to mock the getInstance() method.
Your code should look like that:
#Test
void saveContractTest() {
Contract changedContract = new Contract(...);
try (MockedStatic<ContractDAO> mockedContractDAO = mockStatic(ContractDAO.class) {
mockedContractDAO.when(ContractDAO::getInstance).thenReturn(contractDaoMock);
when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
Contract givenContract = new Contract(...);
Contract actualContract = service.save(givenContract);
//Assertions
...
}
}
Check the docs here to know a bit more about mocking static methods: https://javadoc.io/static/org.mockito/mockito-core/3.9.0/org/mockito/Mockito.html#static_mocks
In Service.save() I have not replaced the line
result = ContractDao.getInstance().saveContract(contract);
with line
result = contractDao.saveContract(contract);
So, we need to use a field instance which we mocked and not the singleton.getInstance().

Error when using the same string in different tests

I have the following scenario:
I perform several tests (#Test) and tests in Cucumber, in Selenium Webdriver, Java.
The tests are going well. However, I want to leave a string stored in one #Test (public void) in another #Test (public void). I cannot.
Could anyone help?
First test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Second test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Method one
public String one() {
if (this.cnpj == null) {
this.cnpj = add.cnpj(false);
} else {
}
return this.cnpj;
}
Both tests I want you to use the same generated string !!!!
I look forward and thanks in advance!
I'm not sure what your method one() does, but assuming you want to use the same value for two different tests, why not just do this:
OneClass oneClass = new OneClass();
String yourGeneratedString = oneClass.one();
// First test
#Test
public void testDocuments() {
yourFunction(yourGeneratedString);
}
// Second test
#Test
public void testDocuments2() {
yourOtherFunction(yourGeneratedString);
}
If I understand correctly, you need this.cnpj value to be available within the second test?
Each time you do new OneClass() , it creates a new instance of it.
So you can do one of the following:
Use singleton instance of OneClass
Make cnpj a static field within OneClass
If I understand it right, you want to share data from one test to second one. If you user testNG then you can do it this way.
import org.testng.ITestContext;
import org.testng.annotations.Test;
public class MyTest {
#Test
public void testOne(ITestContext context){
context.setAttribute("myKey", "myValue");
}
#Test
public void testTwo(ITestContext context){
String valueFromTestOne = (String) context.getAttribute("myKey");
System.out.println("My key = " + valueFromTestOne);
}
}

How to check that a method is not being called using JUnit Mockito Verify

I have a class for which I am writing a JUnit test. I am trying to test if a particular method is never called.
public class CountryProcess extends AbstractCountryProcess {
private static final Logger log = LoggerFactory.getLogger(CountryProcessor.class);
private static final Long MAX_FILE = 20l;
#Override
protected boolean processCountry(Region region, City city) {
Long maxFile = region.getRequiredLongValue(SIZE);
if (maxFile < MAX_FILE) {
cntDao.addCountryLandMark(city);
}
else {
log.warn("File size was big");
}
return true;
}
And the test class is:
public class CountryProcessTest {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final CntDao cntDao = context.mock(CntDao.class);
#Before
public void setup() {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(cntDao.class).toInstance(cntDao);
}
});
}
#Test
public void shouldIgnoreIfFileSizeBiggerThanPermitted() {
//some code to make it trigger ELSE statement above...
verify(cntDao, never()).addCountryLandMark(anyString());
}
}
But this returns the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type $Proxy4 and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
Any idea how I can fix this in the current context. Please give an example using current code so I get a better idea?
You are mixing two mocking frameworks:
jMock - JUnitRuleMockery
Mockito - verify method
Clearly, they are not compatible with each other.
Your verify call looks ok, I believe it will work as soon as it receives a mock created with Mockito (Use Mockito.mock(CntDao.class))
As an alternative to never you can use Mockito.verifyNoMoreInteractions or Mockito.verifyZeroInteractions, but they are less specific.
In addition to the answer from #Lesiak, here is a reproducible example based on your code with both conditions tested and BDD implementation as well (commented out).
#ExtendWith(MockitoExtension.class)
class CountryProcessTest {
#Mock CountryDAO cntDao;
#Mock
Region region;
#Mock
City city;
#InjectMocks
CountryProcess countryProcess;
#Test
void processCountryLargeSize() {
// given
given(region.getRequiredLongValue()).willReturn(100L);
// when
countryProcess.processCountry(region, city);
// then
verifyNoInteractions(cntDao);
// then(cntDao).shouldHaveNoInteractions(); // BDD implementation
}
#Test
void processCountrySmallSize() {
// given
given(region.getRequiredLongValue()).willReturn(10L);
// when
countryProcess.processCountry(region, city);
// then
verify(cntDao).addCountryLandMark(city);
verifyNoMoreInteractions(cntDao);
// then(cntDao).should().addCountryLandMark(any()); // BDD implementation
// then(cntDao).shouldHaveNoMoreInteractions(); // BDD implementation
}
}
The rest of the classes here are provided for reference.
Region
public class Region {
private int size;
public Long getRequiredLongValue() {
return Integer.toUnsignedLong(size);
}
}
AbstractCountryProcess
public abstract class AbstractCountryProcess {
CountryDAO cntDao;
protected abstract boolean processCountry(Region region, City city);
}

Mocking chained methods calls using PowerMock

I have a class which I would like to test with a public static method that contains some chained method calls. Assuming that an exception occurs during the chained method calls, how do I handle this effectively and make it return some specific value?
Following is the code sample of the test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class,CodeWithYetAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = PowerMockito.spy(new CodeWithYetAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithYetAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithYetAnotherPrivateMethod);
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
PowerMockito.doReturn(true).when(codeWithYetAnotherPrivateMethod, "getGambling");
//PowerMockito.doReturn(codeWithYetAnotherPrivateMethod).when(codeWithAnotherPrivateMethod, "getGambleValue");
PowerMockito.spy(CodeWithPrivateMethod.class);
CodeWithPrivateMethod.startGamble();
}
}
Following is the code sample for the class under test
public class CodeWithPrivateMethod {
public static void startGamble() {
Boolean gamble = CodeWithAnotherPrivateMethod.getGambleValue()
.getGambling();
if (gamble) {
System.out.println("kaboom");
}else{
System.out.println("boom boom");
}
}
}
Following is the code sample for the class that gets called from the class under test
public class CodeWithAnotherPrivateMethod {
static CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = new CodeWithYetAnotherPrivateMethod();
public static CodeWithYetAnotherPrivateMethod getGambleValue() {
return codeWithYetAnotherPrivateMethod; //works fine
return null; // fails
}
}
Following is the code sample for the other class that gets called from the class under test
public class CodeWithYetAnotherPrivateMethod {
public Boolean getGambling() {
return false;
}
}
So Assuming I return a null value from getGambleValue() method of CodeWithAnotherPrivateMethod class, how do I handle this null value effectively in my testclass?
This is how to specify expected exceptions using Mockito:
#Test(expected = NullPointerException.class)
public void when_gambling_is_true_then_always_explode() throws Exception {
...
Before I found out about this I would do:
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// setup omitted
try {
CodeWithPrivateMethod.startGamble();
}
catch(NullPointerException e) {
// expected
return;
}
fail("Expected NullPointerException");
}
EDIT: Testing multiple classes that call each other statically like this is a severe code smell. Unit tests should test a single class and inline static calls should be limited to utility classes.
Another comment: your example class names are very confusing. Next time please stick with Foo, Bar, Baz or Appple, Pear, Banana.
If you are not getting an NPE then I expect your mocking/spying is interfering. If you call the code under test without mocking/spying the call chain would be:
CodeWithPrivateMethod.startGamble();
->
CodeWithYetAnotherPrivateMethod value = CodeWithAnotherPrivateMethod.getGambleValue();
->
return null;
<-
value.getGambling();
<- throws NullPointerException
What exactly are you trying to find out or achieve?
EDIT: Here's how it should work with PowerMock
#RunWith(PowerMockRunner.class)
#PrepareForTest(CodeWithAnotherPrivateMethod.class)
public class CodeWithPrivateMethodTest {
#Mock
private CodeWithYetAnotherPrivateMethod yetAnotherInstance;
#Test
public final void testStartGamble() {
// SETUP
mockStatic(CodeWithAnotherPrivateMethod.class);
expect(CodeWithAnotherPrivateMethod.getGambleValue())
.andReturn(yetAnotherInstance);
Boolean gamblingValue = true;
expect(yetAnotherInstance.getGambling()).andReturn(gamblingValue);
replayAll();
// CALL
CodeWithPrivateMethod.startGamble();
// VERIFY
verifyAll();
}

Verify method in constructor was called

I have a constructor that calls a method, like this:
public Foo(boolean runExtraStuff) {
if (runExtraStuff){
doExtraStuff();
}
}
The doExtraStuff() method is running some additional commands that are not easily mocked themselves (things like database checks to initialize some variables). Perhaps it would be better for the constructor to not do this, but this is the code I have to work with at the moment.
I would like to create a unit test to make sure that doExtraStuff() is called when the boolean runExtraStuff is true and does not run when the boolean is false. I am using JMockit.
However, I'm not sure how to make this happen. Normally I would use a Verifications on a mocked object, but since I am testing the constructor, I can't use a mocked object in this way. So how can I verify that a method within a constructor was called?
It's easy enough, even if it requires partial mocking:
#Test
public void runsSetupWhenRequestedOnFooInitialization()
{
// Partially mocks the class under test:
new Expectations(Foo.class) {};
final Foo foo = new Foo(true);
// Assuming "setup" is not private (if it is, use Deencapsulation.invoke):
new Verifications() {{ foo.setup(); }};
}
#Test
public void doesNotRunSetupWhenNotRequestedOnFooInitialization()
{
new Expectations(Foo.class) {};
final Foo foo = new Foo(false);
new Verifications() {{ foo.setup(); times = 0; }};
}
Of course, it would probably be better to avoid mocking in a case like this; instead, the test should check the state of the object through getters or other available methods, if at all possible.
Well, the straightforward answer doesn't use JMockit at all..
in src/main/java/example..
package example;
public class Foo {
private boolean setupRan = false;
public Foo(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
setupRan = true;
}
public boolean getSetupRan() {
return setupRan;
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
public class FooTest {
private Foo testSubject;
#Test
public void should_run_setup() {
testSubject = new Foo(true);
assertThat(testSubject.getSetupRan()).isTrue();
}
#Test
public void should_not_run_setup() {
testSubject = new Foo(false);
assertThat(testSubject.getSetupRan()).isFalse();
}
}
I'll go out on a limb and guess that you are interested in a partial mock here:
in src/main/java/example..
package example;
public class Foo1 {
public Foo1(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
System.out.println("in setup()");
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;
public class Foo1Test {
// hateful partial mocking of test subject!
#Mocked({"setup()"})
private Foo1 testSubject;
#Test
public void should_run_setup() {
new Expectations() {{
testSubject.setup(); // setup() is called
}};
testSubject = new Foo1(true);
}
#Test
public void should_not_run_setup() {
new Expectations() {{
testSubject.setup(); times = 0;
}};
testSubject = new Foo1(false);
}
}
EDIT 1: Note that you won't see the println output since the method was mocked.
EDIT 2: Set expectations for invocations of testSubject.setup() to times = 0 in second test

Categories