Check if method is not called with Mockito - java

I have a void method that creates objects of type Foo and updates each entry of a list those objects.
When the list passed by parameter is empty it shouldn't create any object, thus not calling any setter method of class Foo.
public static void analyzeList(ArrayList<Something> list) {
for (Something s : list) {
Foo f = new Foo();
f.setSomething(someMethod1(f));
f.setSomething2(someMethod2(f));
s.setFoo(f);
}
}
So, I am trying to use Mockito to check that method analyzeList(ArrayList<Something> list) doesn't call any setter method of class Foo, but am having a hard time doing so, since I never worked with Mockito before.
I wrote this test:
#Test
public void shouldNotCallSettersWhenListIsEmpty() {
Foo fooMocked = mock(Foo.class);
FooLogic.analyzeList(emptyList);
Mockito.verify(fooMocked, times(0)).setSomething(anyInt());
}
This test passes, and it should. But when I change times(0) to times(1), the test keeps passing and it shouldn't, since the list is empty.
What am I doing wrong here?

The Foo object you have in your test and the Foo objects you create in your analyzeList are different. You are creating a new Foo object each time in your code.
Even if you pass a non-empty list Mockito.verify(fooMocked, times(0)).setSomething(anyInt()); will pass because you are not calling any methods on the mocked Foo instance.
But you say that by changing times(0) to times(1), the test still passes. But the test should fail (can you re-check this)
With the current setup, you cannot verify anything on the created Foo f instances1. You can still verify the setFoo calls you make on Something if the list you pass has mock Something objects.
1unless you use Powermockito or something that allows you to mock new object creations in the code.

In your situation,
I like to use the
InOrder
functionality;
specifically the
InOrder.verifyNoMoreInteractions()
method.
Here is an example:
import static org.mockito.Mockito.inOrder;
import org.mockito.InOrder;
#Test
public void shouldNotCallSettersWhenListIsEmpty() {
Foo fooMocked = mock(Foo.class);
InOrder inOrderVariable = inOrder(fooMocked);
FooLogic.analyzeList(emptyList);
//Mockito.verify(fooMocked, times(0)).setSomething(anyInt());
// Note: added example verify statement.
inOrderVariable.verify(fooMocked).someMethod(paramaters)
inOrderVariable.verifyNoMoreInteractions();
}

Related

Testing object method return values

I have an object under test and want to verify it was configured correctly by testing the return values of methods. Is there a way to do this without creating one test per method?
I'm imagining something like:
assertThat(obj).fieldIs(Obj::methodA, "value1").fieldIs(Obj::methodB, "value1");
You can make a big test method that tests all fields of the object are as they should be, you aren't limited to one assertSomething() per method.
Example:
#Test
public void testFields() {
Object someObj = theObjInstance;
assertEquals("value1", someObj.methodA());
assertEquals("value2", someObj.methodB());
// ...
}

Chain/transform method calls with ByteBuddy

Using ByteBuddy, can I implement one instance method by calling another and transforming the result?
For instance (toy example):
public abstract class Foo {
public String bar() {
return "bar";
}
public abstract int baz();
}
Given the above, can I implement baz such that it calls bar() and returns the length of the returned string? I.e., as if it were:
public int baz() {
return bar().length();
}
Naively, I tried the following:
Method bar = Foo.class.getDeclaredMethod("bar");
Method baz = Foo.class.getDeclaredMethod("baz");
Method length = String.class.getDeclaredMethod("length");
Foo foo = new ByteBuddy()
.subclass(Foo.class)
.method(ElementMatchers.is(baz))
.intercept(
MethodCall.invoke(bar) // call bar()...
.andThen(MethodCall.invoke(length)) // ... .length()?
).make()
.load(Foo.class.getClassLoader())
.getLoaded()
.newInstance();
System.out.println(foo.baz());
However, it looks like I was wrong in thinking andThen() is invoked on the return value of the first invocation; it looks like it's invoked on the generated instance.
Exception in thread "main" java.lang.IllegalStateException:
Cannot invoke public int java.lang.String.length() on class Foo$ByteBuddy$sVgjXXp9
at net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation
.invoke(MethodCall.java:1667)
I also tried an interceptor:
class BazInterceptor {
public static int barLength(#This Foo foo) {
String bar = foo.bar();
return bar.length();
}
}
with:
Foo foo = new ByteBuddy()
.subclass(Foo.class)
.method(ElementMatchers.is(baz))
.intercept(MethodDelegation.to(new BazInterceptor()))
// ...etc.
This ran, but produced the nonsensical result 870698190, and setting breakpoints and/or adding print statements in barLength() suggested it's never getting called; so clearly I'm not understanding interceptors or #This properly, either.
How can I get ByteBuddy to invoke one method and then invoke another on its return value?
Per k5_'s answer: BazInterceptor works if either:
we delegate to new BazInterceptor(), as above, but make barLength() an instance method, or:
we leave barLength() a class method, but delegate to BazInterceptor.class instead of to an instance.
I suspect the 870698190 was delegating to hashCode() of the BazInterceptor instance, though I didn't actually check.
There is not currently a good way in Byte Buddy but this would be an easy feature to add. You can track the progress on GitHub. I will add it once I find some time.
If you want to implement such chained calls today, you can implement them in Java code and inline this code using the Advice component. Alternatively, you can write the byte code more explicitly by creating your own ByteCodeAppender based on MethodInvocation instances where you have to load the arguments manually however.
You use an instance as interceptor, that means instance methods are prefered (maybe static method are not accepted at all). There is an instance method that matches the signature of your int baz() method, it is int hashCode(). The number you are getting is the hashcode of the new BazInterceptor() instance.
Options i am aware of:
Remove static from barLength that way it will actually be used for interception.
Add the class as interceptor .intercept(MethodDelegation.to(BazInterceptor.class))
I would prefer the second option as you are not using any fields/state of the BazInterceptor instance.

Java - Calling private functions of a class from mock of public function in the class

I am looking for a way to test the data in a class that processes the data and then uploads the data in a manner as clean and portable as possible. So I would like to not resort to making public get functions, to avoid anything being able to reach this data. To keep it portable, I would like to avoid using a test database, so that these tests can be ran in any situation.
Class Foo {
private int a;
private int b;
private int c;
private DBSaver dbSaver;
public Foo(DBSaver dbSaver) {
this.dbSaver = dbSaver;
}
public void processData() {
processData();
saveToDB();
}
private void workNumbers() {
a = 1;
b = 2;
c = a + b;
}
private void saveToDB() {
List<Integer> list = new ArrayList<>();
list.add(a); list.add(b); list.add(c);
dbSaver.save(list);
}
}
Test class:
class FooTest {
#Mock
DBSaver dbSaver;
#Mock
Foo foo;
#Test
private void test() {when(dbSaver.save(any(ArrayList<>.class))).then(returnsFirstArg());
foo = new Foo(dbSaver);
Mockito.doThrow(new Exception() {
//Now I would like to get a, b and c so I can ensure that they have the proper values.
}
).when(foo).processData();
}
}
Here is a pastebin version of the code]().
workNumbers() will be executed as normal, and since the save() function has been mocked to do nothing, that code won't do anything too serious.
I would like to ask if there is a way to now get the a, b and c values back in list form, through mocking an exception being thrown. The problem is accessing the private values in Foo through the mocked instance in FooTest.
You are getting unit testing with mocking wrong. There is no point in having this:
#Mock
Foo foo;
Foo is your "class under test". You do not want to mock that. If at all, you might want to create a spy here, in order to do partial mocking.
In your case, you don't need to access those private fields. You see, the key point is that your code will call:
dbSaver.save(list);
at some point. Meaning: you can use Mockitoy to verify that a specific list is passed when save() is called on that mocked dbSaver object.
That is the whole point: you have that mocked dbSaver instance, so you are in total control what happens there. As said, you can verify that its methods are called with a specific argument; or you can even use an ArgumentCaptor in order to access the list passed to that method call.
And then you simply ensure that the list contains the expected content (which would be those three values from your class under test!). See
here for examples how to do that.
Finally: especially that "exception" part is really wrong. There is no need to generate an exception here. You simply push a mocked dbSaver into an instance of Foo, you call a method on that Foo instance; and then you check for the expected results. That's it; anything else is (useless) over-complication of things.

Hot verify method arguments with Mockito when they change after method invocation [duplicate]

I have a Foo class which is SUT and a Bar class, which is its collaborator. Foo calls run(List<Object> values) on the Bar with "expectedList" as an argument. Then, Foo will add a few more elements to this List so that its state will be different from what it was at the time of calling run(). Here's my test case.
#Test
public void testFoo() {
Bar collaborator = spy(new Bar());
Foo sut = new Foo(collaborator);
verify(collaborator).run(expectedList);
}
Note that the collaborator is actually a spy object rather than a mock. This test case will fail because even though run() was called with an argument equal to expectedList, it was modified since and its current value no longer equals expectedList. However, this is the way it is supposed to work, so I'm wondering if there's a way to have Mockito store the snapshot of parameters when a method is called and verify them based on these values rather than the most recent values.
Use an Answer to check the value of the argument when the method is called. You can either throw an AssertionError within the Answer if the value is wrong, or you can store the value, and do your assertion at the end.
The answer of Dawood ibn Kareem worked for me but I lacked an example, also I use Kotlin and Mockito-Kotlin, so my solution is like this:
class Foo(var mutable: String)
interface Bar {
fun run(foo: Foo)
}
#Test fun `validate mutable parameter at invocation`() {
val bar = mock<Bar>()
var valueAtInvocation: String? = null
whenever(bar.run(any())).then {
val foo = it.arguments.first() as Foo
valueAtInvocation = foo.mutable // Store mutable value as it was at the invocation
Unit // The answer
}
val foo = Foo(mutable = "first")
bar.run(foo)
valueAtInvocation isEqualTo "first"
foo.mutable = "second"
bar.run(foo)
valueAtInvocation isEqualTo "second"
}
valueAtInvocation will represent the value of the mutable property foo.mutable at the last invocation of bar.run(foo). Should also be possible to do assertions within the then {} block.
You can't call verify() on an object that is not a mock. Is this what you meant?
Bar collaborator = mock(Bar.class);
Foo sut = spy(new Foo(collaborator));
verify(collaborator).run(expectedList);
Why don't you try using argument capture to acquire the value of expected list when it was run and then you can compare it.
ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);
verify(collaborator).run(listCaptor.capture());
assertEquals(expectedList, argument.getValue());

How to get a handle to a new Object while unit testing?

How would I test this ValueObject created on the fly in SomeClass without stubbing it out using PowerMock etc?
class ValueOBject {
private String x, y;
getters
setters
}
class SomeClass {
public void foo () {
ValueObject vo = new ValueObject();
vo.setX("some string 1");
vo.setY("some string 2");
faa(vo);
}
public void faa(ValueObject vo) {
// do some more logic on vo here
}
}
class SomeClassTest extends TestCase{
public void testFoo() {
SomeClass s = new SomeClass();
s.foo();
// HOW TO DO THIS?
verify(faa(VAlueObject that is created during foo's run));
}
}
I dont want to use PowerMockito or similar libraries to return a MOCKED object!
Rather a REAL object thats created during execution of the method foo() :
// DONT WANT A MOCKED OBJECT
// #Mock
// private ValueOBject vo;
// henNew(GetEmailInformation.class).withNoArguments().thenReturn(getEmailInformation);
The ValueObject is created internally, so it can only depend on object state. You don't need to test internals, you only need to test the side effects of the calls you do.
In this case you don't need to test foo because you know what foo does, it's only a wrapper for faa. Thus, you need to test faa for actions and side effects caused by the global state and the ValueObject input.
If you want to test the foo() does what you expect, you have to test that the side effects that foo() causes are the same that faa(expectedObject) has.
In other words: if foo and faa are public, and the public interface says that foo is a wrapper for faa with a fixed parameter, you need to test that foo does exactly what faa does with the fixed parameter you expect.
So it looks like you want to assert against the ValueObject created in foo() and passed to faa(vo)?
Create a unit test instantiates the expected ValueObject and passes it to faa(vo). Then compare the results of this to the results that occur when you just call foo().
For example:
// in your unit test:
ValueObject testVo = new ValueObject();
// set values as needed
// testVo should represent what you expect the ValueObject instantiated by foo to
// hold *before* it gets passed to faa
faa(testVo);
// assertions against results of faa method
foo();
// assertions *comparing* the results of foo with the results of your manual faa
So for example, if I expect foo to create a ValueObject with X=1 and Y=1, and then for faa to do magic on them such that the ValueObject's end result is X=-1 and Y=2, your unit test will look something like this:
ValueObject testVo = new ValueObject();
testVo.setX(1);
testVo.setY(1);
faa(testVo);
// assertions using your testing library of choice to verify getX() returns -1 and
// getY() returns 2
foo();
// assertions that the end values after foo()'s faa call are -1 and 2 respectively
Now in your dummy examples above, both foo and faa are void methods, so there's no returned value. I am assuming that faa actually does something that is testable -- eg. sets fields, changes values, and so on.
In some comments you left on other answers, you made a note that you have some private and/or protected fields and methods involved. If this is the case, you'll want to look into Java reflection for how to retrieve those values.
But for specifically ripping out the ValueObject instantiated within foo() before it is passed to faa(vo), this is impossible. As I described above, your best bet is to test your expectations of behavior for the ValueObject you expect to be created in foo() and comparing the results of it being passed to faa(vo) with what actually does happen.
This is telling you that the design has tight coupling so maybe inject the object into the method instead.
You might want to consider testing faa() with in foo(). From an OOP standpoint, I would rather the caller of foo() never need to know faa() even existed. Does faa() need to be public?

Categories

Resources