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

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.

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 Test a private field which is behavior relevant

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

How to test the interaction between a method and its two helpers?

I have the following structure of my Java code:
public MyClass {
// some class variables
...
private void process() {
private MyObject obj;
...
obj = createHelper();
...
messageHelper(obj, "One of several possible strings");
...
messageHelper(obj, "Another call with a different string");
...
}
private MyObject createHelper {
MyObject obj = new MyObject();
// some Setter calls
...
return obj;
}
private void messageHelper (MyOject obj, String message) {
...
}
}
I would like to test, that based on properties obj (that I would like to specify), messageHelper() receives the right string. In other words I need to control the result of one method and have access to the parameters of the other.
I'm still very shaky with all this Mock/Stub/Spy stuff.
It seems to me that I need to Spy on MyClass, stub CreateHelper() with a "manually" created object and not sure what for intercepting call parameters for messageHelper().
Also I noted that Wiki cautions against using Spies:
Think twice before using this feature. It might be better to change
the design of the code under specification.
So what would an appropriate Spocky way to accomplish the task?
Slightly Refactored Code: (5/5/14)
public MyClass {
// some class variables
private messageSevice = new messageService();
...
private void process() {
private MyObject obj;
...
obj = new MyObject(parameters ...);
...
if (someCondition) {
messageService.produceMessageOne(obj);
}
...
if (otherCondition) {
messageService.produceMessageTwo(obj);
{
...
}
}
public class MessageService implements IMessageService {
private final static MSG_ONE = "...";
private final static MSG_TWO = "...";
...
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_ONE);
...
}
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_TWO);
}
private void produceMessage(MyObject obj, String message) {
...
}
}
I would greatly appreciate if someone suggests the way it should be tested with Spock.
The caution you're referring to is rightfully there. There's a very good correlation between testable code and good design (I recommend watching this lecture from Michael Feathers to understand why http://www.youtube.com/watch?v=4cVZvoFGJTU).
Using spies tends to be a heads up for design issues since it usually arises from the impossibility of using regular mocks and stubs.
It's a little hard to predict from your example, since you're obviously using pseudo names, but it seems that the design of the MyClass class violates the single responsibility principle (http://en.wikipedia.org/wiki/Single_responsibility_principle), since it does processing, creation and messaging (3 responsibilities).
If you're willing to change your design, so that the processing class (MyClass) will do only processing, you'll be providing another class that does the creation (MyObjectFactory), and yet another class that does the messaging (MyObjectMessager) either through a constructor, setter methods or by dependency injection.
Using this new design, you can create an instance of the class you're testing (MyClass), and pass it mock objects of both the factory and messaging classes. Then you'll be able to verify whatever you want on both.
Take a look at this example (using Mockito):
public class MyClassTest {
#Test
public void testThatProcessingMessagesCorrectly() {
MyObject object = mock(MyObject.class);
MyObjectFactory factory = mock(MyObjectFactory.class);
when(factory.createMyObject()).thenReturn(object);
MyObjectMessager messager = mock(MyObjectMessager.class);
MyClass processor = new MyClass(factory, messager);
processor.process();
verify(factory).createMyObject();
verify(messager).message(EXPECTED_MESSAGE_1);
verify(messager).message(EXPECTED_MESSAGE_2);
...
verify(messager).message(EXPECTED_MESSAGE_N);
}
...
}
Here's a Spock example (untested, double check before using ...):
public class MyClassSpec extends Specification {
def "check that the right messages are produced with the expected object"() {
given:
def messageService = Mock(IMessageService)
def testedInstance = new MyClass()
testedInstance.setMessageService(messageService)
when:
testedInstance.process()
then:
1 * messageService.produceMessageOne(_)
1 * messageService.produceMessageTwo(_)
}
}
If you're a hammer, every problem is a nail
I'd like to call exception-to-the-rule here and say that sometimes stubbing private methods - necessitating spies - can be both correct and useful.
#eitanfar is most likely accurate in his analysis of the function, and 95% of the time this is the case, but as with most things - I believe - not always.
This is for those of us who believe they have an exception but get the usual "code smell" argument.
My example is a complex argument validator. Consider the following:
class Foo {
def doThing(...args) {
doThing_complexValidateArgs(args)
// do things with args
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of non-logic-related code that throws exceptions
}
}
Placing the validator in it's own class IMO seperates the concern too much. (a FooMethodArgumentValidator class?)
Refactoring out the validation arguably significantly improves readability of the doThing() function.
doThing_complexValidateArgs() should not be public
The doThing() function benefits from the reability of a simple call validateArgs(...) and maintains encapsulation.
All I need to be sure of now is that I have called the function within the parent one. how can I do that? well - correct me if I'm wrong - but in order to do that, I need a Spy().
class FooSpec extends Specification {
class Foo {
def doThing(...args) {
doThing_controlTest(args)
doThing_complexValidateArgs(*args)
// do things with args
}
def doThing_controlTest(args) {
// this is a test
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of code
}
}
void "doThing should call doThing_complexValidateArgs" () {
def fooSpy = Spy(Foo)
when:
fooSpy.doThing(1, 2, 3)
then:
1 * fooSpy.doThing_controlTest([1,2,3]) // to prove to ya'll we got into the right method
1 * fooSpy.invokeMethod('doThing_complexValidateArgs', [1, 2, 3]) // probably due to groovy weirdness, this is how we test this call
}
}
Here is my real life example I used for a static private method:
#SuppressWarnings("GroovyAccessibility")
#ConfineMetaClassChanges(DateService) // stops a global GroovySpy from affecting other tests by reseting the metaclass once done.
void "isOverlapping calls validateAndNormaliseDateList() for both args" () {
List list1 = [new Date(1L), new Date(2L)]
List list2 = [new Date(2L), new Date(3L)]
GroovySpy(DateService, global: true) // GroovySpy allows for global replacement. see `org.spockframework.mock.IMockConfiguration#isGlobal()`
when:
DateService.isOverlapping(list1, list2)
then:
1 * DateService.isOverlapping_validateAndNormaliseDateList('first', list1) // groovy 2.x currently allows private method calls
1 * DateService.isOverlapping_validateAndNormaliseDateList('second', list2)
}

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

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