Unit Test a private field which is behavior relevant - java

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...

Related

How do I test parallelStream().map(interface_impl -> method(interface_impl)0.collect(Collectors.toList()) with Mockito's whens?

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)

Unit testing Collection in Java

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?

how to unit test a class which creates new objects

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

Junit, Mockito, how to test a callbacks [duplicate]

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.

Can I use mockito to match an object with an auto updated timestamp?

What would be the best way to something like this where a timestamp is updated automatically before making the mocked call?
Here is some dummy code of what I am trying to test:
public class ThingWithATimestamp {
public Long timestamp;
public String name;
public ThingWithATimestamp(String name) {
this.name = name;
}
}
public class TheClassThatDoesStuff {
private ThingConnector connector;
public TheClassThatDoesStuff(ThingConnector connector) {
this.connector = connector;
}
public void updateTheThing(MyThingWithATimestamp thing) {
thing.timestamp = currentTimestamp();
connector.update(thing);
}
}
Here is what I want to test:
public class TheClassThatDoesStuffTests {
#Test
public void canUpdateTheThing() {
ThingConnector connector = mock(ThingConnector.class);
TheClassThatDoesStuff doer = new ThisClassThatDoesStuff(connector);
doer.updateTheThing(new ThingWithATimestamp("the name"));
verify(connector, times(1)).update(SomeMatcherThatICantFigureOut);
}
I know this code is pretty dumbed down but I think it accurately portrays what I am trying to verify. I basically need a matcher to fill in the test to verify that the timestamp is within X of the current time so I know it got updated correctly and that connector.update was called with the proper timestamp for the object.
I find the most robust way to deal with time-critical code is to wrap up all of your time-critical functions in their own class. I usually call it TimeHelper. So this class might look like the following.
import java.util.Date;
public class TimeHelper{
public long currentTimeMillis(){
return System.currentTimeMillis();
}
public Date makeDate(){
return new Date();
}
}
and it might have more methods of the same type. Now, any class that uses such functions should have (at least) two constructors - the normal one that you'll use in your application, plus a package-private one in which a TimeHelper is a parameter. This TimeHelper needs to be stored away for later use.
public class ClassThatDoesStuff {
private ThingConnector connector;
private TimeHelper timeHelper;
public ClassThatDoesStuff(ThingConnector connector) {
this(connector, new TimeHelper());
}
ClassThatDoesStuff(ThingConnector connector, TimeHelper timeHelper) {
this.connector = connector;
this.timeHelper = timeHelper;
}
}
Now, within your class, instead of writing System.currentTimeMillis(), write timeHelper.currentTimeMillis(). This will, of course, have exactly the same effect; except now, your class has magically become much more testable.
When you test your class, make a mock of TimeHelper. Configure this mock (using Mockito's when and thenReturn, or alternatively doReturn) to return any time values you like - whatever you need for your test. You can even return multiple values here, if you're going to have multiple calls to currentTimeMillis() in the course of the test.
Now use the second constructor to make the object that you're going to test, and pass in the mock. This gives you perfect control of what time values will be used in the test; and you can make your assertions or verifications assert that precisely the right value has been used.
public class ClassThatDoesStuffTest{
#Mock private TimeHelper mockTime;
#Mock private ThingConnector mockConnector;
private ClassThatDoesStuff toTest;
#Test
public void doesSomething(){
// Arrange
initMocks(this);
when(mockTime.currentTimeMillis()).thenReturn(1000L, 2000L, 5000L);
toTest = new ClassThatDoesStuff(mockConnector, mockTime);
// Act
toTest.doSomething();
// Assert
// ... ???
}
}
If you do this, you know that your test will always work, and never be dependent on the time slicing policies of your operating system. You also have the power to verify the exact values of your timestamps, rather than asserting that they fall within some approximate interval.
First:
class TimestampInInterval extends ArgumentMatcher< ThingWithATimestamp > {
public boolean matches(Object arg) {
ThingWithATimestamp thing = (ThingWithATimestamp) arg;
long delta = thing.timestamp - System.currentTimeMillis();
return delta < INTERVAL;
}
}
Second:
verify(connector, times(1)).update(argThat(new TimestampInInterval());
Although the accepted answer is great, there is no need to create a custom TimeHelper class. You can instead just use the java.time.Clock as a dependency in your TheClassThatDoesStuff class as documented in this answer.
java.time.Clock has lots of static factory methods to create clocks with fixed point in time, custom cadences/ticks, and offset from the current moment. These factory methods can be useful during tests.

Categories

Resources