How to mock ArrayList class using using whenNew method - java

I'm trying to mock arraylist to verify the add method but I'm getting the message:
FAILED: testInit
Wanted but not invoked:
arrayList.add(<any>);
-> at AsyncRestTemplateAutoConfigurationTest.testInit(AsyncRestTemplateAutoConfigurationTest.java:95)
Actually, there were zero interactions with this mock.
The test class I've used is:
#Test
public void testInit() throws Exception {
ArrayList<AsyncClientHttpRequestInterceptor> interceptors = Mockito.mock(ArrayList.class);
PowerMockito.whenNew(ArrayList.class).withAnyArguments()
.thenReturn(interceptors);
Mockito.stub(interceptors.add(Mockito.any())).toReturn(true);
asyncRestTemplateAutoConfiguration.init();
Mockito.verify(interceptors).add(Mockito.any());
}
The actual tested code is:
List<AsyncClientHttpRequestInterceptor> interceptors = new ArrayList<>(interceptors);
interceptors.add(new TracingAsyncRestTemplateInterceptor(tracer));
I've declared the test class with
#RunWith(PowerMockRunner.class)
#PrepareForTest(AsyncRestTemplateAutoConfiguration.class)
Where AsyncRestTemplateAutoConfigurationis the class, which I'm using to test. Could anyone please tell me what I'm missing?

Your unit test should verify public observable behavior which is return values and communication with dependencies (which does not nessessarily imply to test only public methods).
That your production code uses an ArrayList to store your data is an implementation detail which you don't want to test since it may be changed without changing the units general behavior, in which case your unittest should not fail.

Don't start learning how to unit test using PowerMockito - it will give you bad habits.
Instead, consider working carefully through the documentation for Mockito and you will see how to structure your classes for better testing.
Ideally, your classes should be such that you do not need PowerMockito to test them and you can just rely on plain old Mockito.
If you can arrive at the point where you can write elegant and simple tests using just Mockito, it will be a sign you have grasped the fundamental concepts of unit testing.
You can start by learning how to inject dependencies through the constructor of the class that can be swapped with mocked test doubles on which behaviour can be verified.
Another point to note is, as per the other answer, the internal ArrayList in your system under test is an implementation detail. Unless consumers of your system under test can access the ArrayList through, say, methods that expose it there is not much point in writing a test against it.
If the state of the internal ArrayList affects something from the point of view of the consumer, then try writing a test against that rather than against the internal property.
Good luck with your journey on unit testing!

Related

How to mock an internal variable with builder

I am writing unit tests and meet a problem with builder:
Here is the class to be test:
public class ToBeTest() {
public void enact(SomeInput input){
Session s = Session.builder().attributeA(input.getA()).build();
s.attributeB("someValue");
}
}
How can I write a test to verify whether Session S set field A and also B successfully? Thanks!
Basically there are two things you can verify on:
input.getA(): mock that instance of SomeInput you provide to your code under test, then you can verify that mocked object later on!
Session.builder() is most likely a static call, so use static mocking to provide a mocked builder object, which you can verify later on, too. See the official documentation for the steps required to do that.
Having said that: your real problem is that you wrote "hard to test code". Surprise, that makes it hard to test. You see, what is the point of having a "method local" Sessions variable in the first place. If that method would return that s, you could then check if it has certain properties. Or if s would be a field of that class, you could then maybe do other checking, to ensure that a correctly configured Session was build.
Long story short: PowerMock(ito) offers the things you need to this code. Read some good tutorials and you shouldn't have much issues. But it would be worthwhile to also invest into improving your code under test to make it easier to test. My rule of thumb is: when you need PowerMock(ito) to test your code, then your production code should be improved.

Mockito Mocking a return value and verify it

I have this class and wants to create a mock to return and verify the return value "50":
QAService.java:
#Path("/QAService")
public class QAService {
#GET()
//#Path("/")
#Produces("text/plain")
public String getServiceInfo() {
return "50";
}
My understanding of mock by defintion is that I can create a fake object of an implementation class and mock functions yet to be developed so I can test the interface.
Still I am creating this test to test mocking without having an interface. How do I verify it?:
QAServiceTest.java:
public class QAServiceTest {
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
}
Junit will only run methods annotated with #Test, so add it
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
Also, you should verify() that your mock expectations actually happened.
verify(qasmock, times(1)).getServiceInfo();
Note that it seems like you want to test QAService, but you really aren't doing that here. You are simply testing a mock. That's not the same thing.
Create the QAService object yourself and use it.
Let's get a couple definitions straight, first:
A unit test is a brief bit of code you write to ensure that the system you've developed is behaving correctly. Unit tests are often created in a framework like JUnit, but do not need to be. For example, a unit test would assertEquals(5, calculator.add(2, 3)).
A mock is an imitation of a real system, which is often used in unit tests. Mocks are often created in frameworks like Mockito or EasyMock, but do not need to be. Mocks are a form of "test double"—the general term for code you substitute in place of your actual systems, for testing purposes—and Martin Fowler defines them more exactly in an article called "Mocks Aren't Stubs".
When writing a unit test, you're trying to test a single unit, which is often called the system under test or SUT for short. Each test will probably have a different system under test, and the point is that the code that you are testing in the test is your real, actual code, not any sort of mock or fake implementation.
In a complex application, your classes will probably need to collaborate with other classes that may or may not be written or tested, which are categorically known as dependencies. Any given class or system may have its own dependencies, and may be a dependency for other systems. Mocking frameworks are good for mocking those dependencies, not for mocking the system under test.
For your example, QAService is the main class you're writing (system under test), and QAServiceTest is the unit test for that system. No mocks are necessarily required.
Let's say that QAService depends on another class not yet written, called "StorageService". You don't necessarily want to wait for StorageService to work before writing QAService's tests, so instead of using a real StorageService you use a mock. Again, in the unit test called QAServiceTest, you use a real QAService and mock its dependency StorageService.
Even though you don't have StorageService written, you probably have some expectation about how QAService will use that class. Maybe you know that when you call storageService.store(qaRecord), it should return a numeric ID like 101. Even without the code working, you can create a Mockito mockStorageService, and prepare it like this:
when(mockStorageService.store(expectedQARecord)).thenReturn(101);
Now let's say that at the end of the test, you want to ensure that the method of QAService that you're testing will absolutely call storageService.delete(101). A Mockito mockStorageService would check that like this:
verify(mockStorageService).delete(101);
It is often unnecessary to verify statements you have made with when, because the test is unlikely to succeed unless the system under test calls the mock correctly to get that return value (101 here).
Now let's say that you've written another block of code called QAApplication, which you're testing in a unit test called QAApplicationTest, that depends on QAService. You may not have QAService finished or tested, and using a real QAService would require a StorageService, so instead you use mock QAService with a real QAApplication in your unit test called QAApplicationTest.
So, to sum up, a mock works within unit tests to mock the dependencies of the system under test. In your situation, QAServiceTest will not need a mock QAService, but may be used to mock the dependencies of QAService. If you do need a mock QAService, you'll need it when testing another class where QAService itself is a dependency.

What's the best way to unit test classes that delegate the work to others?

I have a question about how best to tackle JUnit testing of a top level class. Imagine I have a class, SomeWriter, that has a method that reformats a String and writes it to a stream. The method doesn't actually do the work but instead delegates it to a member object that actually does the real work. I've summarised this in the class below.
public class SomeWriter {
public void writeReformattedDataToStream(OutputStream outStream, String message) {
myReformatter.DoTheActualWorkAndWriteDataToStream(outStream, message);
}
}
Now in this hypothetical example, I've already written my unit tests for the myReformatter class and I've demonstrated that myReformatter works. My question is, how should I tackle the unit testing of the writeReformattedDataToStream in SomeWriter?
If I were black box testing, I would need to write the same test as I applied to the myReformatter class because I wouldn't know how it implements the task. However, unit testing is really white box testing, so is it valid for the test merely to ensure that myReformatter is being correctly called?
The bottom line is should my test of writeReformattedDataToStream effectively repeat the test of myReformatter, or mock myReformatter and just check it's being called correctly?
I appreciated this is similar to JUnit Test - Class invokes methods in other class
Immediate delegation like this usually falls under the heading of "too simple to test", but if you have some absolute requirement for it, then you need to mock your OutputStream (using EasyMock or a similar tool) and myReformatter and verify that the delegate calls the appropriate method.
As chrylis says, you should not test this method.
There is actually nothing to test.
If you write a test case that tests that the delegate / service is called, then your test is bound to the implementation of the tested method.
So any change in the implementation of the method would require to change the test; and I am sure that you do not want that.
Try injection. For testing purposes you could inject your own implementation of the myReformater class that simply checks that the method was called correctly and returns. Then you are testing your test class in isolation.

How to write a UT to mock an internal object in one method?

For example , I have a java class as below. I am going to write a unit test for doWork(), so I would like to control obj's behavior. But it is obvious that obj is instantiated internally.
How can I write this UT? Now I am using Junit+Mockito.
class ToBeTest{
public ToBeTest(){}
public boolean doWork(){
OtherObject obj=new OtherObject();
return obj.work();
}
}
Thanks in advance. :)
BTW, The reality is I am writing UT for other person's class. So I don't want to change it. It has been fully tested by integration test.
If you can't change the code, you can use Powermock along with junit and Mockito to mock the construction of new objects.
#Test
public void testDoWork() throws Exception{
MyTest mytest = new MyTest();
OtherObj obj = new OtherObj();
obj.test="mocked Test"; //here you can add any other needed values to obj
PowerMockito.whenNew(OtherObj.class).withNoArguments().thenReturn(obj);
String result = mytest.doWork();
Assert.assertTrue(result.equalsIgnoreCase("mocked Test"));
}
The best way is to write code to support testing (Test-Driven Development is emphasizing this). At the moment, your code is written in the way which makes it difficult to test.
Please consider using dependency injection, because it helps you mock the dependent object.
This is a classical example where you should use dependency injection.
In short, instead of creating the object (dependency) internally, you pass it in the constructor or use a factory to create what you want (the factory returns the real implementation in production code and another in test). This gives you the possibility to change the implementation when you test.
Look at the examples following the like I provided or google for "Java dependency injection example".
You can't easily. I can think of two ways you can do this and neither are supported out of the box by Mockito or jUnit as far as I'm aware:
1) Byte code manipulation using cglib or similar library which would be moderately difficult to do and likely pretty fragile.
2) Alternate classloader. You can build a classloader that looks for an attempt to load the OtherObject class and replaces it with an anonymous OtherObject class that gives you the mocking behavior that you are looking for.
Most of the time you should be treating it as a dependency though. If you want to test opening a file, you probably actually want to test with a file so using the concrete class is probably fine. If you want to test a method's behavior that has opening a file as a part of it's logic, you could easily move that out to a dependency and then mock it out. In fact, that usually makes sense because what you store in a file one day, may need to be stored in a database another or be pulled down from the cloud on a third day, so segregating the logic around what you do with the file from the actual process of opening a retrieving the contents is often a logical separation of concerns anyway.
It's very easy:
import org.junit.*;
import mockit.*;
#Test
public void justMockIt()
{
new NonStrictExpectations() { OtherObject o; { o.work(); result = true; }};
assert new ToBeTest().doWork();
}
... when using JMockit.
You have written your code, and now you want to unit test it. This is the fundamental cause of your difficulty. I suggest a different approach.
Express what the doWork() method is meant to do in terms of behaviour that can be observed only through public and protected (getter) methods of the ToBeTest class, or the public and protected methods of any objectys associated-with ToBeTest objects. Take a look at the Javadoc provided with the Java library: that describes what all those classes do without stating the bodies of the methods. When does yor method return true? When does it return false? What side effects does it have? You might find you need to add some getter methods to do this. You could express these in the Javadoc for your own code.
Use the required behaviour to decide what kinds of assertions you can place in your unit-tests.

unit test best practice for method with mocks in Mockito

Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).

Categories

Resources