I have a unit test that will allow me to iterate through a Collection object containing a list of vehicle. Upon each iteration, I want to check to see if the vehicle is an instance of automobile. So my code looks a bit like this:
public class VehicleChecker {
protected boolean checkVehicles(Garage garage) {
for (Vehicle vehicle : garage.getVehicles() {
if (vehicle instanceof Automobile) return true;
}
}
}
So I wrote my code accordingly:
#Mock private Garage mockGarage;
#Mock private VehicleCollection mockVehicleCollection;
#Mock private VehicleCollectionIterator mockVehicleCollectionIterator;
#Mock private Vehicle mockVehicle;
#Test
public void testCheckVehicles() {
VehicleChecker testObject = new vehicleChecker();
when(mockGarage.getVehicles()).thenReturn(mockVehicleCollection);
when(mockVehicleCollection.iterator()).thenReturn(mockVehicleCollectionIterator);
when(mockVehicleCollectionIterator.hasNext()).thenReturn(true).thenReturn(false);
when(mockVehicleCollectionIterator.next()).thenReturn(mockVehicle);
boolean result = testObject.checkVehicles(mockGarage);
verify(mockGarage).getVehicles();
}
The problem occurs with the verify statement. Based on how it was written, the test should pass. When I step through the code, however, I the code just skips the for loop entirely. Why is that? Is there a difference in the way one iterates through a Collection as opposed to an ArrayList? If so, how do I properly mock that interaction?
Are you sure you have initialized mocks with MockitoAnnotations.initMocks?
Related
So I am creating a unit test utilising Mockito.
A component of the code I'm testing looks like this:
public Object validateObject(final Parameter param) {
Object validated_object = new Object();
final List<Object> processed_objects = interface_impl_list.parallelStream()
.map(interface_impl -> parallelTask(interface_impl))
.collect(Collectors.toList());
for (final Object object : processed_objects) {
validated_object = object;
if (Object.getResult == PASSED) {
break;
}
}
return validated_object;
private Object parallelTask(InterfaceObj interface_impl) {
return validate_object(interface_impl);
}
Our teams 'template' for unit tests would look something like this:
#Spy
private List<InterfaceObj> interface_impl_list;
#Mock
private InterfaceImpl1 interface_impl_1;
#Mock
private InterfaceImpl2 interface_impl_2;
#BeforeEach
void setup() {
interface_impl_list.add(interface_impl_1);
interface_impl_list.add(interface_impl_2);
}
#Test
void myTest() {
// Variables needed
final int x = 1
// Return variables
...
// when()'s
// Not sure how to do this for parallelStream
when(interface_impl1.method()).thenReturn(returnVariable1); //i.e. within validateObject()
when(interface_impl2.method()).thenReturn(returnVariable1);
// Method being tested
final Object object = classBeingTested.findWillToGoOn(x);
// verify()'s
verify(interface_impl1, times(2)).method();
verify(interface_impl2, times(2)).method();
// assertions
...
}
I can't seem to find any examples of someone using whens or general unit testing examples for parallelStream.forEach().map().collect() that I can apply here.
How would I go about this? Is there any examples people could even point to?
Thanks in advance
So the parallelStreams is a recent addition. Previously the code would just call the parallelTask consecutively so I would just add when's in order of when that external class method was called.
I played around with doing when(interface_impl_list.parallelStreams.map().collect(Collectors.toList())) and some variations but I can't get past any intial compile errors and figure out how to go about it.
Edit: Error Message without mocking/adding when for the stream or any of the map or collect methods
java.lang.NullPointerException at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:327)
first of all: I found few solutions for my problem but the "newest" one was from 2014 and used reflections so I hope I could maybe find some more advanced solutions for my question.
Thats the case and its about migrateUser and canAdd. This is an example class to make my question easily visible.
public class UserInterfaceImpl implements UserInterface {
private final List<T> accountList = new LinkedList<>();
private final AccountInterface accountInterface;
private boolean bonusReceived = false;
public UserInterfaceImpl(AccountInterface accountInterface) {
this.accountInterface = accountInterface;
}
public void migrateUser(AccountMergerInterface accountMerger, UserInterface oldUser) {
boolean success = accountMerger.performChange(this, oldUser);
if (success && !bonusReceived) {
//addBonus
accountInterface.deposit(1);
bonusReceived = false;
}
}
public boolean canAdd() {
return accountList > 0;
}
public AccountInterface getAccount() {
return accountInterface;
}
}
The migrateUser method changes the some account Data which is not relevant for my test because I would test it separately of course (should be like that what I read so far).
So I wonder, how can I see if the behavior of that class changes the bonusReceived correctly? Without using reflections and do it as sophisticated as possible?
My first attempt was that:
#Test
public void testMigrateUser() {
AccountMergerInterface test = mock(AccountMergerInterface.class);
// define return value for method getUniqueId()
when(test.performChange()).thenReturn(true);
}
But now I cannot continue. The rule should be in my example to have no getter and setter! The class should be like my example.
I don't know how to:
set bonusReceived to false before migrateUser is executed that accountInterface.deposit(1); is not executed
see if bonusReceived will be set to false if the if() continue is true.
Same questions for the List: how can I access the private field of List, add an Object so that the return value is true or false. Or should I "simulate" a List and if yes, how can I do that?
Thanks in advance!
Unit tests check public observable behavior.
There is no point in verifying internal state of an object since this may change to support other behavior. You don't want to change your unit test in that case...
So mock the AccountMergerInterface (as you already did) and the AccountInterface and verify that your class under test calls the methods on them in the right order with the right parameters:
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
private AccountMergerInterface accountMergerInterface;
#Mock
private AccountInterface accountInterface;
#Test
public void testMigrateUser() {
// arrange
when(test.performChange()).thenReturn(true);
// act
new UserInterfaceImpl(accountInterface).migrateUser(accountMergerInterface);
// assert
InOrder inOrder Mockito.inOrder(accountMergerInterface, accountInterface);
inOrder.verify(accountMergerInterface).deposit(1);
inOrder.verify(accountInterface).whatEverToCallNext();
}
Same questions for the List:
There is currently no code dealing with the list in UserInterfaceImpl.
You cannot verify behavior which is not there...
I have the following Java code:
Index userNameIndex = userTable.getIndex("userNameIndex");
ItemCollection<QueryOutcome> userItems = userNameIndex.query("userName", userName);
for (Item userItem : userItems) {
}
I am trying to write a unit test and I would like to mock the ItemCollection<QueryOutcome>. The issue is that the iterator returned by ItemCollection<QueryOutcome>::iterator is of type IteratorSupport, which is a package protected class. Therefore, it is impossible to mock the return type of this iterator. What can I do instead?
Thanks!
The previous answer is valid. However, if you can mock Iterable instead of ItemCollection, your life will be easier.
Iterable<Item> mockItemCollection = createMock(Iterable.class);
Iterator<Item> mockIterator = createMock(Iterator.class);
Item mockItem = new Item().with("attributeName", "Hello World");
expect(mockItemCollection.iterator()).andReturn(mockIterator);
expect(mockIterator.hasNext()).andReturn(true).andReturn(false);
expect(mockIterator.next()).andReturn(mockItem);
replay(mockItemCollection, mockIterator);
for(Item i : mockItemCollection) {
assertSame(i, mockItem);
}
verify(mockItemCollection, mockIterator);
BTW, I'm a big fan of static imports at least in the test code. It makes it more readable.
Reading the AWS code, I would consider their code to have a design flaw. It doesn't make sense to return a package scope class from a public interface. It's probably something that should be raised as an issue to them.
You could also always wrap the ItemCollection into a correctly typed class:
public class ItemCollectionWrapper<R> implements Iterable<Item> {
private ItemCollection<R> wrapped;
public ItemCollectionWrapper(ItemCollection<R> wrapped) {
this.wrapped = wrapped;
}
public Iterator<Item> iterator() {
return wrapped.iterator();
}
}
This may not be the best way to do it, but it works and may require you to change the way you get the iterator in the class under test.
#Test
public void doStuff() throws ClassNotFoundException {
Index mockIndex;
ItemCollection<String> mockItemCollection;
Item mockItem = new Item().with("attributeName", "Hello World");
mockItemCollection = EasyMock.createMock(ItemCollection.class);
Class<?> itemSupportClasss = Class.forName("com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport");
Iterator<Item> mockIterator = (Iterator<Item>) EasyMock.createMock(itemSupportClasss);
EasyMock.expect(((Iterable)mockItemCollection).iterator()).andReturn(mockIterator);
EasyMock.expect(mockIterator.hasNext()).andReturn(true);
EasyMock.expect(mockIterator.next()).andReturn(mockItem);
EasyMock.replay(mockItemCollection, mockIterator);
/* Need to cast item collection into an Iterable<T> in
class under test, prior to calling iterator. */
Iterator<Item> Y = ((Iterable)mockItemCollection).iterator();
Assert.assertSame(mockItem, Y.next());
}
I'm using JUnit and Mockito to test some classes. The class itself creates an object from another class. A list called testList. Here my code:
public class A {
private List<B> bList;
//returns the bList
public List<B> getBList() {
return bList;
}
//checks the status by calling getStatus in class B
public Status getStatus() {
//status is an enum consists of PASSED and FAILED
Status finalStatus = Status.PASSED;
for (B be : this.getTestList()) {
if (be.getStatus() != Status.PASSED) {
finalStatus = Status.FAILED;
break;
}
}
return status;
}
}
public Class B {
private Status status = Status.FAILED;
public getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
What would be the best way to test the getStatus and getTestList methods in the class called Test.
Thank you very much....
I looked at your ClassA and I wondered how bList ever gets set to anything. Right now, there's no way for it to be anything other than null, which means that getStatus will throw a null pointer exception every time.
Your problem is that you are thinking about how to test methods instead of thinking about how to test behaviour. One reason why this is a problem is that your class has to fit in with the rest of your application in a certain way. To be sure that it does that, it needs certain behaviour, not certain details within each method. So the only meaningful test is one that checks the behaviour.
Perhaps more insidious is the fact that testing individual methods makes you focus on the code that you have in fact written. If you are looking at your code while you write your test, then your test becomes a self-fulfilling prophecy. You may have missed a whole set of behaviour that your class is required to provide; but if you only test the behaviour that your class does provide, you'll never know.
So, back to the problem in hand. I see four, maybe five behaviours that your class might be expected to fulfil. Maybe there are more - it's hard to tell if you only show us the code, and not the specification. You should write a test for each one. I strongly believe that the name of each test should describe the behaviour, rather than reflecting the name of the methods that the test uses. In this case, I might choose names like this.
public void statusIsPassedWhenEveryTestPassed()
public void statusIsFailedWhenEveryTestFailed()
public void statusIsFailedWhenSomeTestsPassedSomeFailed()
public void statusIsPassedWhenNoTests()
public void statusIsPassedWhenTestsNotSet() // this one currently fails
Within each test, I would create an object of ClassA, then do whatever has to be done to set the bList within the object. Lastly, I would call getStatus and assert that the return value is what I want. But the important point is that each test (except the last one) uses more than one method of ClassA, so these are not tests of an individual method.
You can provide setters (or constructor injection) for the objects in question as protected and then extend the class inside your test case to mock the objects or you can try using something like powermock. You would still need to provide a way to set those objects in question.
I guess it depends on how you can populate testList in a unit test. If you have, say, a setter, then you would not need any mocking frameworks
class TestTest {
Test test = new Test();
#Test void should_return_failed_if_a_single_test_failed() {
givenTestListWithOneFailedTest();
assertThat(test.getStatus(), is(Status.FAILED))
}
void givenTestListWithOneFailedTest() {
test.setTestList(createSomeTestListWithOnlyOneFailedTest());
}
#Test void should_return_passed_if_all_tests_passed() {
// ...
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Intercept object on method invocation with Mockito
I have an class that can mapp from one format to another. Since this is legacy code I don't dare to rewrite it, it is basically a set of plugins so if I change one I might have to change all the other. It wasn't developed with testing in mind.
So this is my problem.
interface Mapper {
void handle(ClassA classA);
void handle(ClassB classB);
}
public interface Publisher {
public void publish(MappedClass mappedClass);
}
class MyMapper implements Mapper {
private Publisher publisher;
public void setPublisher(final Publisher publisher) {
this.publisher = publisher;
}
public handle(ClassA classA) {
final MappedClass mappedClass = // Map from ClassA to MappedClass
publisher.publish(mappedClass);
}
public handle(ClassB classB) {
final MappedClass mappedClass = // Map from ClassB to MappedClass
publisher.publish(mappedClass);
}
}
Okay. So depending on which class was "handled" MappedClass will be published with different values, and it is the values I want to verify (test). The problem is that I will get a test where I first have to write code that tests that the publish method is called,
private boolean wasCalled;
#Test
public void testClassAMapped() {
wasCalled = false;
final MyMapper myMapper = new MyMapper();
myMapper.setPublisher(new Publisher() {
public void publish(final MappedClass mappedClass) {
wasCalled = true;
// Code for verifying the fields in mappedClass
});
}
final ClassA classA = // Create classA
myMapper.handle(classA);
assertTrue(wasCalled);
}
So first we create our mock Publisher which will first set the state of wasCalled to true so we know this method was ever called (this example is simplified so there is actually a dispatcher in the code... legacy code so I don't want to change it), second I want to verify that MappedClass has the correct field values.
What I would like to know is if anyone knows a better way to test this? The wasCalled, and wasCalled check becomes more or less boilerplate code for many of my tests, but since I don't want to add that much clutter (own hacks, test base classes, etc) I would like to know if there is a way to do this in Mockito, or EasyMock?
Use an Mockito ArgumentCaptor
#Test
public void test(){
Publisher publisher = Mockito.mock(Publisher.class);
myMapper.setPublisher(publisher);
ArgumentCaptor<MappedClass> captor = ArgumentCaptor.forClass(MappedClass.class);
....
myMapper.handle(...);
...
verify(publisher).publish(captor.capture());
MappedClass passedValue = captor.getValue();
// assert stuff here
}
I'm not sure I fully understand the problem, but it looks like you are looking for Mockito.verify(publisher).publish(Matchers.isA(MappedClass.class));
For that to work, you'd have to mock the Publisher through
Publisher publisher = Mockito.mock(Publisher.class)
and then hand that into MyMapper.
If you need to assert the state of the MappedClass, use an ArgumentCaptor. See this answer for an example.
The Mockito-API-doc has many additional examples.