I need to test if one objects calls other object methods in right order.
Unfortunately it looks like Mockito use some kind of grouping for calls with the same parameters. I prepared example which illustrates this behavior.
public class TestInOrder {
#Test
public void test() {
Foo foo = new Foo();
Bar mockBar = mock(Bar.class);
foo.run(mockBar);
InOrder order = Mockito.inOrder(mockBar);
order.verify(mockBar).A();
order.verify(mockBar).B();
order.verify(mockBar).B();
order.verify(mockBar).A();
order.verify(mockBar).B();
}
}
class Foo {
void run(Bar mockBar) {
mockBar.A();
mockBar.B();
mockBar.B();
mockBar.A();
mockBar.B();
}
}
class Bar {
public void A() {
}
public void B() {
}
}
The result is:
org.mockito.exceptions.verification.VerificationInOrderFailure:
Verification in order failure:
bar.B();
Wanted 1 time:
-> at com.goeuro.pi.provider.busfor.TestInOrder.test(TestInOrder.java:19)
But was 3 times. Undesired invocation:
-> at com.goeuro.pi.provider.busfor.Foo.run(TestInOrder.java:32)
I don't understand why I get this error. Order of calls in test is the same as in method.
The issue is that you expect one invocation on each mock. Instead Mockito will count all the invocation on certain mock and will fail when 2 in a row will happen.
This is the implementation for verify method in InOrderImpl class.
public <T> T verify(T mock) {
return this.verify(mock, VerificationModeFactory.times(1));
}
As you can see, it tells mockito to expect exact one invocation on method.
From JavaDoc:
Allows verifying exact number of invocations.
Use VerificationMode to tell Mockito how to verify you mock. This should help:
InOrder order = Mockito.inOrder(mockBar);
order.verify(mockBar).A();
order.verify(mockBar, times(2)).B();
order.verify(mockBar).A();
order.verify(mockBar).B();
Related
I have a simple function which was recently wrapped by some additional logic. I am struggling with updating the test logic since suddently, the method body is wrapped in a mock.
Let me give you an example.
Former logic & test:
// logic
public void doSomething(Transaction t, int a) {
myService.foo(t, a);
}
And my test:
// test
TestedService service;
#Mock
MyService myService;
#Mock
Transaction t;
#Test
public void testSomething() {
testedService.doSomething(t, 10);
Mockito.verify(myService).foo(t, 10);
}
What happened is that we wrapped our logic in some additional function:
public void doSomething(Transaction t, int a) {
model.runInEnhancedTransaction(t, t2 -> { myService.foo(t2, a) });
}
My question is, how do I test this when the logic is suddently wrapped in in model method (model is a mock in my test).
I basically need to verify that t2 -> { myService.foo(t2, a) } was called when the model object is a mock.
EDIT: I made it work with implementing my custom version of model just for the test purpose but still wonder if there is some more elegant way.
It's kind of tough to test these kinds of lambda invocations. What I do is perform two tests: one that model.runInEnhancedTransaction() was called, and one for model.runInEnhancedTransaction() itself. eg
#Test
void doSomethingCallsModelEnhancedTransaction() {
testedService.doSomething(t, 10);
verify(model).runInEnhancedTransaction(eq(t), any());
}
#Test
void modelRunInEnhancedTransaction() {
Transaction t = mock(Transaction.class);
BiConsumer<Transaction, Integer> consumer = mock(Biconsumer.class);
model.runInEnhancedTransaction(t, consumer);
verify(consumer).accept(...);
}
I am new to Mockito, please help in understanding the basic.
According to me above code is supposed to print 5 when mocked.add(6,7) gets called , but add() method is not getting called and the code prints 0.. why ? any solution for this code ?
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class Calc{
int add(int a,int b){
System.out.println("add method called");
return a+b;
}
}
class MockTest{
public static void main(String[] args) {
Calc mocked=mock(Calc.class);
when(mocked.add(2,3)).thenReturn(5);
System.out.println(mocked.add(6,7));
}
}
In order to get result of 5, you have to pass the exact params as when you set up the when..then. Otherwise mockito will return a 'default' value (which is 0 for integer:
What values do mocks return by default?
In order to be transparent and unobtrusive all Mockito mocks by
default return 'nice' values. For example: zeros, falseys, empty
collections or nulls. Refer to javadocs about stubbing to see exactly
what values are returned by default.
If you want to return 5 for any integer then use:
when(mocked.add(Mockito.any(Integer.class),Mockito.any(Integer.class))).thenReturn(5);
A "mock" is just an empty dummy object that simulates behaviour of a "real" object. If you define a behaviour such like when(mocked.add(2,3)).thenReturn(5); you specifically tell this mock what to do, when it receives those exact values.
mocked.add(6,7) will return 0 at that point, since you haven't defined its behaviour for those values and therefore uses a default value. So if you want to cover all possible inputs, you can go with the solution #MaciejKowalski posted and use the generic matchers like Mockito.any(Integer.class).
Still I believe it is not clear how to correctly handle mocks. Mocks are a way of providing external dependencies to a system-under-test without the need to set up a whole dependency tree. The real methods inside that class are usually not called. That's what something like when(mocked.add(2,3)).thenReturn(5); means. It tells the mock to behave like the real dependency without actually having it at hand.
An example could look like this:
public class TestClass {
private ExternalDependency dep;
public void setDep(ExternalDependency dep) {
this.dep = dep;
}
public int calculate() {
return 5 + dep.doStuff();
}
}
public class ExternalDependency {
public int doStuff() {
return 3;
}
}
Now in your test code you can use mocks like this:
#Test
public void should_use_external_dependency() {
// Aquire a mocked object of the class
ExternalDependency mockedDep = Mockito.mock(ExternalDependency.class);
// Define its behaviour
Mockito.when(mockedDep.doStuff()).thenReturn(20);
TestClass sut = new TestClass();
sut.setDep(mockedDep);
// should return 25, since we've defined the mocks behaviour to return 20
Assert.assertEquals(25, sut.calculate());
}
If sut.calculate() is invoked, the method in ExternalDependency should not be really called, it delegates to the mocked stub object instead. But if you want to call the real method of the real class, you could use a Spy instead with Mockito.spy(ExternalDependency.class) or you could do that with when(mockedDep.doStuff()).thenCallRealMethod();
Which are differences between andAnswer() and andDelegateTo() methods in EasyMock in terms of usage?
First difference
I know that when andAnswer method is used, it is skipped the constructor call. This is important if the constructor makes extra things.
class Dummy {
public Dummy(Object someArgument) {
// some validations of arguments
System.out.println("the constructor is called");
}
public Object method() {
System.out.println("the method is called");
return new Object();
}
}
#Test
public void testSt1() {
Dummy mock = EasyMock.createMock(Dummy.class);
EasyMock.expect(mock.method()).andAnswer(new IAnswer<Object>() {
#Override
public Object answer() throws Throwable {
System.out.println("mocked method is called");
return new Object();
}
} );
EasyMock.replay(mock);
mock.method();
}
#Test
public void testSt2() {
Dummy mock = EasyMock.createMock(Dummy.class);
EasyMock.expect(mock.method()).andDelegateTo(new Dummy(new Dummy(new Object()) {
#Override
public Object method() {
System.out.println("mocked method is called");
return new Object();
}
} );
EasyMock.replay(mock);
mock.method();
}
Results:
testSt1() does not call the constructor of Dummy
testSt2() calls the constructor of Dummy
What are the other differences?
The purpose of the two methods is to provide different levels of responsibility for your tests. Your example isn't that great, though.
Here's a simple method that demonstrates how functionally these two provide different test expectations.
public String foo() throws Exception {
throw new Exception();
}
With andAnswer, you can make a mocked version of this method return a String, even though it would never return one in practice. Your use of andAnswer implies an expected response.
With andDelegateTo, this will always throw an Exception. Your use of andDelegateTo implies an actual response.
andAnswer means your test-specific code will handle the response. For example, if you create a ParrotAnswer for a MockDao update method, the Parrot will return the updated Object, but no Dao is actually instantiated in the process. This is nice for unit testing where you basically walk the test subject through, but doesn't help if your mocked method doesn't do as what you method actually does.
andDelegateTo allows you to provide an actual Object implementing the interface to handle the response. We're allowing our test subject controlled access to a resource, rather than providing unrestricted access to a full resource. benefit of this is that you can test integration into a test environment, but minimize actual changes to the test environment. For example, you can delegate get to a wired Dao to fetch an actual live value from the Db, and mock the delete method, so you don't actually delete that same value during testing (and having to recreate it again later to do the same test if it has a static id, for example).
I have the following class
public final class Foo {
private Foo() {}
public static void bar() {
if(baz("a", "b", new Object())) { }
}
private static boolean baz(Object... args) {
return true; // slightly abbreviated logic
}
}
And this is my Test:
#PrepareOnlyThisForTest(Foo.class)
#RunWith(PowerMockRunner.class)
public class FooTest {
#Test
public void bar() {
PowerMockito.mockStatic(Foo.class); // prepare
Foo.bar(); // execute
verifyPrivate(Foo.class, times(1)).invoke("baz", anyVararg()); // verify - fails
}
}
For that, I get the following error message - and I don't understand why...
Wanted but not invoked com.example.Foo.baz(
null );
However, there were other interactions with this mock.
Removing the prepare line above seems to make the verify line pass no matter for how many times you check for... :(
(Our SONAR code checks enforce that each test has some sort of assertXyz() in it (hence the call to verify()) and enforces a very high test coverage.)
Any ideas how to do this?
The problem with your code is that you mock Foo so your method implementations won't be called by default such that when you call Foo.call() it does nothing by default which means that it never avtually calls baz that is why you get this behavior. If you want to partially mock Foo, mock it using the option Mockito.CALLS_REAL_METHODS in order to make it call the real methods as you seem to expect, so the code should be:
#PrepareOnlyThisForTest(Foo.class)
#RunWith(PowerMockRunner.class)
public class FooTest {
#Test
public void bar() throws Exception {
PowerMockito.mockStatic(Foo.class, Mockito.CALLS_REAL_METHODS); // prepare
...
}
}
I'm new to Mockito, and think it rocks for mocking. I've just come across a case where it doesn't seem like i'm able to get it to work - that being, replacing a method of a normal object with a mock method, without the method getting called when I try to mock it.
Here's a super simplified example of what I'm trying to do, that sadly, doesn't duplicate the error, but seems to be exactly the same as my real code.
public class SimpleTest
{
public class A
{
}
public class B
{
public int getResult(A anObj)
{
throw new RuntimeException("big problem");
}
}
#Test
public void testEz()
{
B b = new B();
B spy = spy(b);
// Here are both of my attempts at mocking the "getResult" method. Both
// fail, and throw the exception automatically.
// Attempt 1: Fails with exception
//when(spy.getResult((A)anyObject())).thenReturn(10);
// Attempt 2: In my real code, fails with exception from getResult method
// when doReturn is called. In this simplified example code, it doesn't ;-(
doReturn(10).when(spy).getResult(null);
int r = spy.getResult(null);
assert(r == 10);
}
}
So currently when I run my test, the test fails by throwing an exception when I try and mock the "getResult" method of the spy. The exception is an exception from my own code (ie a runtime exception), and it happens when I try and mock the "getResult" method = ie when executing the "doReturn" line above.
Note that my real use case is more complex of course... the "B" class has lots of other methods that I want to leave as is, and just mock the one method.
So my question is how can I mock it so the method isn't called?
MAJOR NOTE: I just rewrote the entire test from scratch and it works fine now. I'm sure I had a bug in their somewhere, but it's not there now - the method isn't called when it's mocked using the spy! and for what it's worth, I'm using the doReturn syntax in mocking the method.
doReturn(10).when(spy).getResult(null);
Your reedited question works just fine now.
This commented line is wrong
when(spy.getResult((A)anyObject())).thenReturn(10);
Should be
when(spy.getResult(any(A.class))).thenReturn(10);
Full test (method isn't called)
public class SimpleTest {
public class A {
}
public class B {
public int getResult(A anObj) {
throw new RuntimeException("big problem");
}
}
#Test
public void testEz() throws Exception {
B b = new B();
B spy = spy(b);
doReturn(10).when(spy).getResult(null);
int r = spy.getResult(null);
assert (r == 10);
}
}
Result
Tests Passed: 1 passed in 0,176 s