Testing object method return values - java

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());
// ...
}

Related

I want to use spy to mock a method but i need to get some dummy data in return

I want to mock the getUserDataFromExt() and pass the local hashmap and expecting it to return some list of data and also add/assign some values to the passed in hashmap.
Note: I cannot inject that hashmap from constructor and mock it.
public List<Report> getUserData() {
.............
..............
Map<String, Set<Integer>> studyToRelationshipPk = new HashMap<>();
List<NetworkUserSiteDetail> uniqueList = getUserDataFromExt(studyToRelationshipPk);
..............
}
Is there a way that i can mock the method and still get the data from passed in local argument and return some list.
If you can't refactor your code, you will need to create a spy for your class (to mock for getUserDataFromExt).
Then you can use thenAnswer to modify your HashMap and return the list:
when(spy.getUserDataFromExt()).thenAnswer(
new Answer() {
public Object answer(InvocationOnMock invocation) {
// get your method arguments
Object[] args = invocation.getArguments();
// do whatever with your hashmap
// return your list
return ...
}
}
);
If you can refactor your code, it would probably be better to move the method getUserDataFromExt to a different method and mock it. You could still use the same way to modify both the parameter and the result.
You'll also might want to consider changing the behaviour of the method - as modifying the parameter and return a result - can be quite unexpected from the view of others developers.

how to intercept parameter with mockito for a normal array of objects?

This might sound like a very easy question but I am really struggling to archive the solution.
Normally I mock and match quite easily my arguments.
Now I am matching a method that is like this:
getAppFacebookClient(page, V2_11).publish(destination, JsonObject.class, parameters.asArray());
this is for a facebook application and the parameters is a list of a custom Object. the asArray[] method was created in the class and basically does something like this:
public Parameter[] asArray() {
return parameters.toArray(new Parameter[parameters.size()]);
}
and the Parameter of this return is of the type com.restfb.Parameter
So, I am basically doing this
when(client.publish(anyString(), eq(JsonObject.class), any(com.restfb.Parameter[].class))).thenReturn(result);
but seems like it is never taken and of course I cannot manipulate result,
Any idea how could I mock this kind of objects in a proper way?
I also tried the other way
doReturn(result).when(client).publish(anyString(), eq(JsonObject.class), any(com.restfb.Parameter[].class));
Your code is correct ... unless the publish uses varargs!
In such a case you need to use any() / anyVararg() matcher.
Consider:
#Mock Thingy testee;
interface Thingy {
int f(String... arg);
}
#Test
public void test() {
// given
// works only if signature is `f(String[] arg)`
// when(this.testee.f(Mockito.any(String[].class))).thenReturn(42);
when(this.testee.f(Mockito.any())).thenReturn(42); // anyVararg() is deprecated
// when
final int result = this.testee.f(new String[] { "hello", "world" });
// then
assertThat(result, comparesEqualTo(42));
// works only if signature is `f(String[] arg)`
// verify(this.testee).f(Mockito.any(String[].class));
verify(this.testee).f(Mockito.any());
}

Check if method is not called with Mockito

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();
}

Unit-test wrapper methods when base method is private [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 6 years ago.
I read this answer about unit-test a wrapper method. In following code:
public static Object methodA(Object arg) {
if (arg == null) {
return null;
} else {
return methodB();
}
}
It looks reasonable that I don't need to test all functionality in methodB(), just test 2 cases where arg is null and not because methodB() should be tested already.
However, if methodB() is private method, I should test all functionality that methodB() will provide because according to another answer, private methods are implementation details.
The problem is, if I have 2 methods methodA1() and methodA2() and they all call methodB() like this:
public static MyObject methodA1(int x) {
MyObject obj = new MyObject();
obj.setX(x);
return methodB(obj);
}
public static MyObject methodA2(int y) {
MyObject obj = new MyObject();
obj.setY(y);
return methodB(obj);
}
private static MyObject methodB(MyObject obj) {
// doSomething with obj
return obj;
}
Should I test methodA1() and methodA2() separately? Or I can just test the private method methodB() because methodA1() and methodA2() are just wrapper methods of methodB(), so if methodB() is correctly tested, I won't need to test methodA1() and methodA2() at all.
EDIT:
I wrote separate tests for public methods at first. But the problem is, if there are many variations of the methodA, and some of the functionalities / requirements are shared in some of them, then the code of the test cases will be duplicated. That's why I wonder if I should test private method methodB().
The real problem I met is I have requirement to add a record in database, and there are many different APIs I should provide. For example, I should provide:
MyObject addMale(String name, String job); // fill sex with "Male"
MyObject addStudent(String name, String sex); // fill job with "Student"
And all of them checks the parameter is valid or not, fill the field that is not specified and call the private method to actually insert the record into the database, which is so called methodB().
There are many APIs like this, so if I can only test methodB() with all fields situation, maybe I can reduce the duplication of the test cases, but is that a good practice to do the unit tests like this?
EDIT2:
I know I can test private methods because I used reflection in my other test cases, and I know it can invoke private methods, too. But my question is about in this situation, testing private methods is a proper solution or not.
This is actually a question I've wondered about for awhile, and while it's not necessarily correct, I'll share my opinion.
The main problem is that private methods are hard to test. I did some Googling, and there some tools and techniques that let you access private methods (reflection is the main one I encountered), but they seemed a little convoluted.
But the reason you wrote a private method is because there is another method, a public method, that calls it. So while you can't directly test the private method, you can check its functionality by testing the public method which calls it.
If I were you, I would extensively test methodA1() and methodA2(), ensuring that all the functionality of methodB() is tested by the tests you run on the public methods.
You've received a few opinions why you should write unit tests for methodA1() and methodA2(); you've pushed back on them. You asked the question here; you are clearly looking for some justification for not writing complete unit test for them. Let's see if we can give you the answer you want. ;-)
From what you've added in your edit, it looks like you have a variation on a builder pattern. Eg)
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
How would we test the builder?
Since the builder has 4 attributes, which could be set in any order, there would be 4! = 24 different orderings. A complete test suite would have to include:
#Test public void testXYZW() { ... }
#Test public void testXYWZ() { ... }
// ... 21 more permutations ...
#Test public void testWZYX() { ... }
But is that all? No! Some of those attributes could have default values, so we would have to test those patterns as well. Total orderings is now P(4,4)+P(4,3)+P(4,2)+P(4,1)+P(4,0) = 24+24+12+4+1 = 85 unit test.
#Test public void testXWY() { ... }
#Test public void testWY() { ... }
#Test public void testZ() { ... }
// ... 61 more permutations ordering
And this only tests each permutation of X, Y, Z, W attributes with one test value per attribute per test. It is clearly unwieldy to write an exhaustive set of tests for every possible combination and permutation.
The designer of the builder class would understand that the permutation of the attribute settings does not affect the resulting construction; writing tests for permutations of the order does not actually increase the test coverage. Tests for omitted attributes are useful, as they test the default values. Testing of different combinations of the omitted attributes again would not increase the test coverage. So, after careful thought, only two tests might be required:
#Test
public void testXYZW() {
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
assertThat(o.wasBuiltProperly());
}
#Test void testDefaults() {
MyObject o = new Builder().build();
assertThat(o.wasBuiltProperlyFromDefaults());
}
If proper, complete testing of methodB() is being done, then you could safely get away with testing only the validation of inputs in methodA1() and methodA2().
#Test void testMethodA1Professor() {
MyObject o = methodA1("professor");
assertThat(o.wasBuiltProperlyWithProfessor());
}
#Test void testMethodA1WithNull() {
MyObject o = methodA1(null);
assertThat(o.wasBuiltProperlyWithNull());
}
Oftentimes, when a private method is used by multiple methods inside a class, there's a distinct concept lurking behind it. It may deserve to have its own class.
it should not be used outside of the class
There are a few ways you could extract methodB to its own class and not make it available as part of your public API :
Nest it inside the class that uses it and give it a restricted scope
Put it in another module at a lower level. Make that module available from your API but not from the clients.

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