Having trouble with a mock object unit test - java

I'm toying with mock objects and I'm having trouble setting up a unit test that checks if a list is being properly sorted. The conceit of this is that I'm mocking a clock, but simply using the times() method isn't working. The list should be in ascending order, but getting the first index simply returns whatever value was set last.
For reference, here is a working mock test that tests the clock being set at midnight:
#Test
public void shouldSetAtMidnight() {
expect(mock.instant()).andReturn(Instant.from(this.midnight));
expect(mock.getZone()).andReturn(this.timeZone);
replay(mock);
this.st.setDesiredValue(72);
SetPoint[] sched = this.st.getSchedule();
verify(mock);
assertEquals(LocalTime.MIDNIGHT, sched[0].getScheduledTime());
}
Here, setting the desired value is only important in that it adds a SetPoint to the array (setDesiredValue creates a SetPoint which has an int and a LocalTime). This is where I'm having difficulty:
#Test
public void shouldOrderTwoSetPointsAddedOutOfOrder() {
expect(mock.instant()).andReturn(Instant.from(this.midnight)).times(2);
expect(mock.getZone()).andReturn(this.timeZone).times(2);
replay(mock);
this.st.setDesiredValue(73);
this.st.setDesiredValue(71);
SetPoint[] schedule = this.st.getSchedule();
verify(mock);
assertEquals(71, schedule[0].getTemp());
}
setDesiredValue is supposed to associate an int value with a LocalTime, which in this case should be midnight. It then adds a SetPoint with those characteristics to the list and calls Collection's sort() method to sort them from lowest to highest. Now, I'm assuming that my problem here is that I'm associating two values with the exact same time despite calling times(2) for both expects, but I just recently started with mock objects and just don't have the knowledge of them to know where to go from here. Running this test returns 73 instead of 71.

Your assumption is correct. When you say .andReturn(Instant.from(this.midnight)).times(2), the exact value passed to .andReturn is repeated twice.
You could do .andReturn(Instant.from(this.midnight)).andReturn(Instant.from(this.midnight)), which will give you two instants. But as a general rule, this is very bad form for a unit test. Instant.from(this.midnight) comes from outside the test, so you can't predict if calling this function twice will result in the same value or different values, making the test non-deterministic. Okay for an integration test, not okay for a unit tests, where you would be using mocks. It is better to use a real number, like .andReturn(Instant.fromEpochSecond(10)).andReturn(Instant.fromEpochSecond(15)).
You're not providing a whole lot of details about st and any reasons why you think the test should not return 73 instead of 71.

Related

Unit testing void public methods

I have a class that I am trying to write a few unit tests for, specifically, a void method within the class. Im not entirely sure whether or not the fact that the method is void is of any consequence here, but this is the basic structure of the class.
public class MyClass {
private Map<String,Object> myMap;
public void process(Bucket bucket){
//parses bucket, updates myMap
}
public int getAnswer(String input){
//searches map data
}
}
The basic usage of the class is that the process method is called for each bucket to ingest it’s data, and the getAnswer method returns a summation of sorts about the data that has been processed from the buckets.
I’ve written a few unit tests for the getAnswer method, but since the process method doesn’t return anything, but rather just updates the internal state of my object, is there a way to properly unit test it? Since it’s a public method, I figured that it needed to be unit tested, but haven’t figured out how to do so, independent of the getAnswer method.
We would need more code to answer you in details, but in short the answer is yes, you can and should definitely test it.
process is going to make some side-effects somewhere, right? Either you inject Mockito mocks of the classes/interfaces these side-effects are effected upon, or if you have an in-memory version of them you inject that instead.
In the case of mocks, you'll want to carefully assert that the side-effect methods were called exactly with the right parameters. If you're using an in-memory simulation, you check the state of your in-memory object and check it conforms to what you expected.
For unit testing of process method, I think you can do following:
Verify input bucket can be able to parse based on your method comments.
Exception handling -- if applicable -- if bucket is unable to parse.
For map update / add, you can always check if initial size is changed & valid bucket made successful attempt to add to map. If bucket key already present, you can also verify if size of map remains same.
All above points are based on information provided in original question & it is independent of getAnswer method.

Struggling with unit testing and mocking

I am trying to mock the following method:
public void add(Question question) {
String username = authenticationManager.getUsername();
Candidate candidate = userService.getByUsername(username);
if (!authenticationManager.hasPermission("ROLE_ADMIN")) {
question.setStatus(QuestionStatus.WAITING);
}
question.setCandidate(candidate);
questionRepository.add(question);
}
This is my attempt:
#Test
public void add_savesQuestionWithStatusWaiting_whenSubmittedAsUser() {
Candidate candidate = new Candidate();
Question question = mock(Question.class);
when(authenticationManager.getUsername()).thenReturn("andreas");
when(userService.getByUsername("andreas")).thenReturn(candidate);
when(authenticationManager.hasPermission("ROLE_ADMIN")).thenReturn(true);
questionService.add(question);
verify(question, times(0)).setStatus(any(QuestionStatus.class));
}
What I am trying to do is to test application logic. When the user does not have ROLE_ADMIN the question status will be set to waiting. Am I doing the mocking right?
In unit testing you mock every dependency that is not the part of the tested unit.
In your case your unit is questionRepository and you are trying to test whether all expected interaction on the objects occur but not on the real objects but on their mocked versions. That is perfectly fine and natural approach.
So in terms of how you use mockito you are doing pretty good. What is not ok is that questionService.add is doing a way too much. 'add' suggests that it will put some object in a container and nothing else. Instead it is also doing a complex question object setup. In other words it has side effects. The result is that the number of different boundary conditions you have to test is big. That will make your tests hard to maintain in future. Look how many mocks you had to create.
If you come back to your test after some time and you will try to figure out what is it doing will this be simple ?
I also think that the test name is not reflecting what is actually tested. For me 'add_savesQuestionWithStatusWaiting_whenSubmittedAsUser' implies that I should expect that at the end question should be saved with status set to 'waiting' instead you use verify to check if there was no call to setStatus().
I would try to refactor the add method code so all it does is element insertion into queryService. Then I would test different boundary conditions for questionService ( for example how it will behave when null will be provided ). I would also move setup of question to a different layer of your application and have that tested in a different unit.

capturing previous values to verify mock object

In mockito, is it possible to capture the previous value set to a field of an object passed to a mock object's method for example the method under test performs this
public void methodUnderTest(){
Person person = new Person();
person.setAge(5);
someObject.setPerson(person);
...
person.setAge(6);
someObject.setPerson(person);
}
What I wanted to know is if I mock someObject, will I be able to verify that someObject performed setPerson to a single object "person" twice but the object had different value for age when setPerson occurred? I tried using ArgumentCaptor but since I passed the same object, I was just able to get the last age.
ArgumentCaptor<Integer> arg = ArgumentCaptor.forClass(Integer.class);
verify(mockObject).setPerson(arg.capture());
List<Integer> captureList = arg.getAllValues();
captureList.get(0).getAge(); // returns 6
captureList.get(1).getAge(); // returns 6
I also tried doing
InOrder in = inOrder(mockObject);
in.verify(mockObject).setPerson(arg.capture());
assertEquals(5, arg.getValue().getAge()); //fails
Unfortunately, you can't do that with an ArgumentCaptor.
The captor only stores a reference to the argument; in this case, it stores twice a reference to the same object, person.
You should try using an Answer, to perform the proper check every time the setPerson method is called.
This mockito issue is related to what you're trying to do.
Can't you just do
verify(mockedList, times(1)).setPerson(eq(5));
verify(mockedList, times(2)).setPerson(eq(6));
Been a while since I used mockito so I think that's the right syntax.
Or do you need to capture the value for some other reason than assertions?
I think it is not possible with Mockito. You may rewrite your code to make it "unit testatble" or much better by writing the test first and the code after in a TDD approach.
However if for some reasons you can't modify your code, it is possible to use PowerMock features. For example PowerMockito.whenNew will allow you to provide a mock of A. But this approach is not recommended.

jUnit test for addAll method

For my assignment, I have to develop several jUnit tests for the method:
addAll(int index, Collection c)
This method is part of the class ArrayList - built in to java.
I figured out how to create the tests and run them in Eclipse IDE, but I'm a little confused as to exactly how I'm supposed to develop the tests. Could I get an example that includes what I should have in a #before, #beforeClass, #after, #test method?
To make this clear, I understand the format of the methods...I just don't understand HOW to test this method.
http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html#addAll(java.util.Collection)
So, what you need to test is that the method inserts all the elements in the passed Collection and that it inserts them into the appropriate position in the ArrayList.
Think of all the possible senerios and test each one.
start with empty arraylist
pass empty collection
use index of 0
use index > 0
etc, etc...
After the add, verify / assert that the ArrayList now has all the elements that it should have in the correct order / locations.
Also test the error cases with #Test(expected=...).
index < 0
index > arrayList.size()
null collection
come up with other ideas
Also... assertThat in combination with Hamcrest's IsIterableContainingInOrder would be helpful for verification.
You will need to think of the behaviour you want to test, and then create a number of methods annotated with #Test to test aspects of that behaviour. Think about how should addAll behave. For example, if a collection passed to it, and an index of 0, then it should add all those elements in index 0 of ArrayList, followed by previously existing objects. So, in your test method, create an ArrayList, stick some objects in it, create a collection (c), stick some objects in it, call addAll on your arrayList with index 0 and collection (c), and assert that it has done what it was supposed to do...
(That's just an example, I am not sure what is the exact expected behaviour of addAll in your case)
Even better take a look at the wikipedia article Vakimshaar posted :)
Stick with #Test and #Before Methods, the rest is probably not what you need.
Methods annotated with #Before get called every time before a method annotated with #Test is executed. You can use it to initialized stuff to a clean state which might be shared among multiple tests.
A starting point could be the following code (for more cases to test take a look at John's answer) and implement them yourself.
public class ArrayListTest {
public ArrayList<String> list;
#Before
public void before() {
// This the place where everything should be done to ensure a clean and
// consistent state of things to test
list = new ArrayList<String>();
}
#Test
public void testInsertIntoEmptyList() {
// do an insert at index 0 an verify that the size of the list is 1
}
#Test
public void testInsertIntoListWithMultipleItems() {
list.addAll(Arrays.asList("first", "second"));
list.addAll(1, Arrays.asList("afterFirst", "beforeSecond"));
// Verify that the list now contains the following elements
// "first", "afterFirst", "beforeSecond", "second"
List<String> theCompleteList = // put the expected list here
// Use Assert.assertEquals to ensure that list and theCompleteList are indeed the same
}
}
Use annotation #Test to mark test method that should return void and should not accept arguments.
For most usages this is enough. But if you want to run specific code before or after each test use implement appropriate method and mark them with #Before and #After annotation.
If you need some code that runs before or after test case (the class where you implement several tests) annotate appropriate methods using #BeforeClass and #AfterClass method. Pay attention that these methods must be static, so "before" method is executed event before the default constructor of your test case. You can use this fact if you wish too.

How can I simplify testing of side-effect free methods in Java?

Functions (side-effect free ones) are such a fundamental building block, but I don't know of a satisfying way of testing them in Java.
I'm looking for pointers to tricks that make testing them easier. Here's an example of what I want:
public void setUp() {
myObj = new MyObject(...);
}
// This is sooo 2009 and not what I want to write:
public void testThatSomeInputGivesExpectedOutput () {
assertEquals(expectedOutput, myObj.myFunction(someInput);
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
// I don't want to repeat/write the following checks to see
// that myFunction is behaving functionally.
assertEquals(expectedOutput, myObj.myFunction(someInput);
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
}
// The following two tests are more in spirit of what I'd like
// to write, but they don't test that myFunction is functional:
public void testThatSomeInputGivesExpectedOutput () {
assertEquals(expectedOutput, myObj.myFunction(someInput);
}
public void testThatSomeOtherInputGivesExpectedOutput () {
assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
}
I'm looking for some annotation I can put on the test(s), MyObject or myFunction to make the test framework automatically repeat invocations to myFunction in all possible permutations for the given input/output combinations I've given, or some subset of the possible permutations in order to prove that the function is functional.
For example, above the (only) two possible permutations are:
myObj = new MyObject();
myObj.myFunction(someInput);
myObj.myFunction(someOtherInput);
and:
myObj = new MyObject();
myObj.myFunction(someOtherInput);
myObj.myFunction(someInput);
I should be able to only provide the input/output pairs (someInput, expectedOutput), and (someOtherInput, someOtherOutput), and the framework should do the rest.
I haven't used QuickCheck, but it seems like a non-solution. It is documented as a generator. I'm not looking for a way to generate inputs to my function, but rather a framework that lets me declaratively specify what part of my object is side-effect free and invoke my input/output specification using some permutation based on that declaration.
Update: I'm not looking to verify that nothing changes in the object, a memoizing function is a typical use-case for this kind of testing, and a memoizer actually changes its internal state. However, the output given some input always stays the same.
If you are trying to test that the functions are side-effect free, then calling with random arguments isn't really going to cut it. The same applies for a random sequence of calls with known arguments. Or pseudo-random, with random or fixed seeds. There's a good chance are that a (harmful) side-effect will only occur with any of the sequence of calls that your randomizer selects.
There is also a chance that the side-effects won't actually be visible in the outputs of any of the calls that you are making ... no matter what the inputs are. They side-effects could be on some other related objects that you didn't think to examine.
If you want to test this kind of thing, you really need to implement a "white-box" test where you look at the code and try and figure out what might cause (unwanted) side-effects and create test cases based on that knowledge. But I think that a better approach is careful manual code inspection, or using an automated static code analyser ... if you can find one that would do the job for you.
OTOH, if you already know that the functions are side-effect free, implementing randomized tests "just in case" is a bit of a waste of time, IMO.
I'm not quite sure I understand what you are asking, but it seems like Junit Theories (http://junit.sourceforge.net/doc/ReleaseNotes4.4.html#theories) could be an answer.
In this example, you could create a Map of key/value pairs (input/output) and call the method under test several times with values picked from the map. This will not prove, that the method is functional, but will increase the probability - which might be sufficient.
Here's a quick example of such an additional probably-functional test:
#Test public probablyFunctionalTestForMethodX() {
Map<Object, Object> inputOutputMap = initMap(); // this loads the input/output values
for (int i = 0; i < maxIterations; i++) {
Map.Entry test = pickAtRandom(inputOutputMap); // this picks a map enty randomly
assertEquals(test.getValue(), myObj.myFunction(test.getKey());
}
}
Problems with a higher complexity could be solved based on the Command pattern: You could wrap the test methods in command objects, add the command object to a list, shuffle the list and execute the commands (= the embedded tests) according to that list.
It sounds like you're attempting to test that invoking a particular method on a class doesn't modify any of its fields. This is a somewhat odd test case, but it's entirely possible to write a clear test for it. For other "side effects", like invoking other external methods, it's a bit harder. You could replace local references with test stubs and verify that they weren't invoked, but you still won't catch static method calls this way. Still, it's trivial to verify by inspection that you're not doing anything like that in your code, and sometimes that has to be good enough.
Here's one way to test that there are no side effects in a call:
public void test_MyFunction_hasNoSideEffects() {
MyClass systemUnderTest = makeMyClass();
MyClass copyOfOriginalState = systemUnderTest.clone();
systemUnderTest.myFunction();
assertEquals(systemUnderTest, copyOfOriginalState); //Test equals() method elsewhere
}
It's somewhat unusual to try to prove that a method is truly side effect free. Unit tests generally attempt to prove that a method behaves correctly and according to contract, but they're not meant to replace examining the code. It's generally a pretty easy exercise to check whether a method has any possible side effects. If your method never sets a field's value and never calls any non-functional methods, then it's functional.
Testing this at runtime is tricky. What might be more useful would be some sort of static analysis. Perhaps you could create a #Functional annotation, then write a program that would examine the classes of your program for such methods and check that they only invoke other #Functional methods and never assign to fields.
Randomly googling around, I found somebody's master's thesis on exactly this topic. Perhaps he has working code available.
Still, I will repeat that it is my advice that you focus your attention elsewhere. While you CAN mostly prove that a method has no side effects at all, it may be better in many cases to quickly verify this by visual inspection and focus the remainder of your time on other, more basic tests.
have a look at http://fitnesse.org/: it is used often for Acceptance Test but I found it is a easy way to run the same tests against huge amount of data
In junit you can write your own test runner. This code is not tested (I'm not sure if methods which get arguments will be recognized as test methods, maybe some more runner setup is needed?):
public class MyRunner extends BlockJUnit4ClassRunner {
#Override
protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
Iterable<Object[]> permutations = getPermutations();
for (Object[] permutation : permutations) {
method.invokeExplosively(test, permutation[0], permutation[1]);
}
}
};
}
}
It should be only a matter of providing getPermutations() implementation. For example it can take data from some List<Object[]> field annotated with some custom annotation and produce all the permutations.
I think the term you're missing is "Parametrized Tests". However it seems to be more tedious in jUnit that in the .Net flavor. In NUnit, the following test executes 6 times with all combinations.
[Test]
public void MyTest(
[Values(1,2,3)] int x,
[Values("A","B")] string s)
{
...
}
For Java, your options seem to be:
JUnit supports this with version 4. However it's a lot of code (it seems, jUnit is adamant about test methods not taking parameters). This is the least invasive.
DDSteps, a jUnit plugin. See this video that takes values from appropriately named excel spreadsheet. You also need to write a mapper/fixture class that maps values from the spreadsheet into members of the fixture class, that are then used to invoke the SUT.
Finally, you have Fit/Fitnesse. It's as good as DDSteps, except for the fact that the input data is in HTML/Wiki form. You can paste from an excel sheet into Fitnesse and it formats it correctly at the push of a button. You need to write a fixture class here too.
Im afraid that I dont find the link anymore, but Junit 4 has some help functions to generate testdata. Its like:
public void testData() {
data = {2, 3, 4};
data = {3,4,5 };
...
return data;
}
Junit will then thest your methods will this data. But as I said, I cant' find the link anymore (forgot the keywords) for a detailed (and correct) example.

Categories

Resources