How do I write a Mockito test case? - java

Hi I was writing a test case for
#Override
public SnapDocument updateFlights(SnapDocument snapDocument, FlightListingResponse flightsResponse) {
HashMap<String, FaresInfo> outboundFlights = new HashMap<>();
HashMap<String, FaresInfo> inboundFlights = new HashMap<>();
Objects.requireNonNull(flightsResponse.getOutboundFlights()).getFlights().forEach(faresInfo -> outboundFlights.put(faresInfo.getJourneySellKey(), faresInfo));
Objects.requireNonNull(flightsResponse.getReturnFlights()).getFlights().forEach(faresInfo -> inboundFlights.put(faresInfo.getJourneySellKey(), faresInfo));
snapDocument.setOutboundFlights(outboundFlights);
snapDocument.setInboundFlights(inboundFlights);
return snapDocument;
}
This is the test case I have written
public void updateFilghtsSuccess(){
when(snapService.getSnapDocument(any())).thenReturn(snapDocument);
when(snapService.updateFlights(snapDocument, flightListingResponse)).thenReturn(snapDocument);
verify(snapService).updateFlights(snapDocument, flightListingResponse);
}
The build is failing, How to write the test cases for this so that I can improve the coverage of my code?

when, given and verify should only be used when dealing with mocks.
As your code works with plain old java objects and no other external components are called, you do not need them.
Just construct the pojos to pass to the method and assert that the pojo that comes back out contains the correct values. You don't need mockito for that, as the test does not require mocks.
#Test
void testUpdateFlights() {
// Arrange
SnapService snapService = new SnapServiceImpl();
SnapDocument sd = new SnapDocument();
FlightListingResponse response = new FlightListingResponse();
response.setOutboundFlights(...);
response.setReturnFlights(...);
// Act
SnapDocument result = snapService.updateFlights(sd, response);
// Assert
assertThat(result.getOutboundFlights()).contains(...);
}
You do not need them now, but when would you need a mock? If your code calls a component that is not under test and you don't want that the actual implementation of it is executed. Unit tests are to test 1 unit of work. All other external components should be mocked out.

Related

How to test that a method is called by Guava Cache only once

I'm trying to test that a cache I created is working properly, and duplicate calls to a method aren't actually called multiple times, but loaded from my cache.
I'm using LoadingCache from Google Guava to accomplish this.
So my naive approach was to create a spy, and verify that the method was called once. I then figured out that because spy() is a decorator, I can only see if the method was called on that object. Since the method is being called by LoadingCache, my spy cannot verify it.
How do I best test that my cache is being used properly?
(note: I could make a LoadingCache dependency, and check that the correct method is called, but then I don't know if my cache is working. Maybe the hash is calculated in a way I didn't anticipate, and so it actually is calling the method every time. I want to actually see the effect)
private final LoadingCache<TaskDetails, byte[]> cache;
...
cache = CacheBuilder.newBuilder()
.maximumSize(cacheSize)
.expireAfterAccess(Duration.ofMinutes(cacheDurationInMinutes))
.build(CacheLoader.from(this::doTask));
public byte[] taskCaller(...) {
...
return cache.getUnchecked();
}
public byte[] doTask(...) {
if(something.doSomething() ... ) {
...
}
First test attempt doesn't work, Mockito says: Wanted but not invoked (the method was "never called", since the spy doesn't know the cache called it)
#Test
public void test() {
// given
TaskService spy = spy(
new TaskService(...)
);
// when
for (int i = 0; i < 3; i++) {
spy.taskCaller(...);
}
// then
//if caching is working, we should only do the real work once
verify(spy, times(1)).doTask(any(TaskDetails.class));
}
Second attempt: NullPointerException on first statement in the method ( something.doSomething() ), I'm not completely sure why, but I'm convinced for the same reason as before
#Test
public void test() {
// given
TaskService spy = spy(
new TaskService(...)
);
final int[] counter = {0};
when(spy.doTask(any())).thenAnswer(invocation -> {
counter[0]++;
return new byte[]{0,0,0,0};
});
// when
int run = 3;
for (int i = 0; i < run; i++) {
spy.taskCaller(...);
}
// then
//if caching is working, we should only do the real work once
assertThat(run).isEqualTo(counter[0]);
verify(spy, times(1)).doTask(any(TaskDetails.class));
}
Two ideas:
Enable cache stats recording, interact with the cache, get the cache stats, then verify that the load count (and possibly other stats) are what you expect.
Make your CacheLoader a separate named class rather than a method reference, an instance of which is passed to CacheBuilder.build(), and arrange for that instance to be a mock in your test. You can then verify method call counts and arguments on your mock loader.
I'm using LoadingCache from Google Guava to accomplish this.
That's the point. If you trust Guava enough, why don't you trust that its tests work?
Did you write the cache? No, you didn't. Then don't test it as part of unit tests: only as part of integration tests, with the rest of the whole application.
Just test that the cache-loading method is called when you invoke your cache-using method.
If you want to test that you have a cache, perform two calls on the general method, and verify that the cache-loading method is called only once.

How to Create a JUnit Test of a List<Overview>

I am currently stuck trying to create a unit test for this piece of code I have. I honestly can't figure out at all how to create a unit test for these lines of code. I have looked multiple places online and couldn't find anything. Its probably just because I don't understand unit test so I can't figure out how to create this one but could someone help me please?
public List<Overview> findOverviewByStatus(String status) throws CustomMongoException {
List<Overview> scenarioList = new ArrayList<Overview>();
LOGGER.info("Getting Scenario Summary Data for - {}", status);
Query query = new Query(Criteria.where("status").is(status));
if (mongoTemplate == null)
throw new CustomMongoException("Connection issue - Try again in a few minutes",
HttpStatus.FAILED_DEPENDENCY);
LOGGER.info("Running Query - {}", query);
scenarioList = mongoTemplate.find(query.with(new Sort(Sort.Direction.DESC, "lastUpdatedDate")), Overview.class);
return scenarioList;
}
So you want to unit test the method. Start with pretending you don't know what the code looks like (black box testing).
What happens if you call it with status of null, and then status of empty string?
What are some status string that return expected values?
Add all these as asserts to your test method to make sure that if someone changes this method in the future the unit test makes sure that it returns the expected result.
That is all a unit test usually does, makes sure that the code behaves in a predictable way and safeguard against change that violates a contract you created for the method when you wrote it.
For example:
import org.junit.Assert;
import org.junit.Test;
public class MyObjectTest {
#Test
public void testMyObjectMethod() {
// Create the object that contains your method (not in the sample you provided)
MyObjectToTest obj = new MyObjectToTest();
// Check that for a null status you get some result (assuming you want this)
Assert.assertNotNull(obj.findOverviewByStatus(null));
// Lets assume that a null status returns an empty array, add a check for it
Assert.assertTrue("null parameter size should be 0", obj.findOverviewByStatus(null).size() == 0);
//etc...
}
}

Multiple classes for one testclass

I have a testclass with #Parameters that looks like this:
#Parameterized.Parameters
public static Collection<Object[]> data() {
log.info("Starting test class for laan documents");
controller = new Controller();
List<Laan> calculations = controller
.getXMLValues(Controller.Type.LAAN)
.stream()
.map(object -> (Laan)object)
.collect(Collectors.toList());
ArrayList<Path> xmlFiles = new ArrayList<>();
calculations.forEach(s -> xmlFiles.add(s.getXmlPath()));
log.info("Getting log for " + xmlFiles.size() + " laan files");
logvalues = controller.getLogvalues(xmlFiles);
Collection<Object[]> params = new ArrayList<>();
for(Laan laan : calculations) {
if(laan.getDocumentType().equalsIgnoreCase("laan")) {
for(Logfile logfile : logvalues) {
if(logfile.getName().equalsIgnoreCase(laan.getName())) {
params.add(new Object[]{laan.getName(), laan, logfile});
}
}
}
}
log.info("");
return params;
}
Most of the objects contains the same variables with different values, but there are some cases where there is nothing to compare with in the logfile (which is no problem and in most cases normal). Those cases are handled with a test in the beginning of the test method assumeTrue(someCondition);
Now the test class is getting very big and hard to maintain. At the moment there is about 30 test methods in the class and there will be added about 100 new test methods in the upcoming days. I've read that it's bad practise to create a new class and use pointers to other test classes.. So how should I go ahead to and organize my very long testclass?
You need to define your architecture of your test framework. Try to seperate methods by another directories and classes. For example:
If you need to test some functionality like: LoginPage, Dashboard, Email - it doesn't mean that you need to keep all methods in one test class. Create basic api like:
com.myproject.steps
LoginPageSteps.java
DashBoardSteps.java
com.myproject.suite
TestSuite.java
com.myproject.scenarious
LoginPageScenario.java
DashboardScenario.java
After, if you have methods for working only with Dashboard, move them into DashBoardSteps, and for login methods into LoginPageSteps. After, call them from LoginPageScenario or DashboardScenario, this approach will provide you more comfortable conditions for easy support on future.

How to mock DynamoDB batch save?

I wrote the dynamoDB code which stores list of items.
mapper.batchSave(trafficSensorReadings)
This will return.
List<FailedBatch>
I want to mock the mapper.batchSave and then return one failed job. How can I achieve it? I am using mockito and Junit.
I wrote something like this. But not useful.
when(dynamoDBMapper.batchSave(eq(List.class))).thenReturn(mock(List.class));
A complete example follows
#Test
public void test() {
FailedBatch failedBatch = mock(FailedBatch.class);
List<FailedBatch> failedBatchList = new ArrayList<>();
failedBatchList.add(failedBatch);
DynamoDBMapper dynamoDBMapperMock = mock(DynamoDBMapper.class);
when(dynamoDBMapperMock.batchSave(any(List.class))).thenReturn(failedBatchList);
tested.testedMethodCall();
verify(dynamoDBMapperMock).batchSave(any(List.class));
}
First, I think you might want to use Mockito.any() instead of Mockito.eq().
Second, I don't see why you would want to mock the list. You can just create one and return it
// GIVEN
FailedBatch batch1 = /**/;
FailedBatch batch2 = /**/;
List<FailedBatch> failedBatchList = Lists.newArrayList(batch1, batch2);
// WHEN
when(dynamoDBMapper.batchSave(any(List.class))).thenReturn(failedBatchList);
Object someResult = yourFunctionTestCall();
// THEN
verify(someResult)...

How do I run the same JUnit test multiple times with different test data each time?

I am just getting started with unit testing. I did the junit tutorial from a pdf from the tutorial points website. So my question is, I want to test my shunting yard algorithm and my RPNEvaluator.
The constructors (and any other variables to help you out with the context) look like this:
ShuntingYard.java:
private ArrayList<String> tokens = new ArrayList<String>();
public ShuntingYard(ArrayList<String> tokens) {
this.tokens = tokens;
}
RPNEvaluator.java:
private Queue<String> polishExpression;
public RPNEvaluator(Queue<String> exp) {
polishExpression = exp;
}
ShuntingYard.java has a method called toRpn() which will take an ArrayList and return a Queue after some processing.
RPNEvaluator has a method called evaluate which will take a Queue type and return a double after some processing.
With Junit I am trying to write some unit tests and I wanted to know if this start was the best way to go about it:
package testSuite;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
public class ExpressionEvaluationTest {
/**
* Initialise the lists to be used
*/
#Before
public void beforeTest() {
ArrayList<String> exprOne = new ArrayList<String>();
exprOne.add("3");
exprOne.add("+");
exprOne.add("4");
exprOne.add("*");
exprOne.add("2");
exprOne.add("/");
exprOne.add("(");
exprOne.add("1");
exprOne.add("-");
exprOne.add("5");
exprOne.add(")");
exprOne.add("^");
exprOne.add("2");
exprOne.add("^");
exprOne.add("3");
ArrayList<String> exprTwo = new ArrayList<String>();
exprTwo.add("80");
exprTwo.add("+");
exprTwo.add("2");
ArrayList<String> exprThree = new ArrayList<String>();
exprThree.add("2");
exprThree.add("/");
exprThree.add("1");
exprThree.add("*");
exprThree.add("4");
ArrayList<String> exprFour = new ArrayList<String>();
exprFour.add("11");
exprFour.add("-");
exprFour.add("(");
exprFour.add("2");
exprFour.add("*");
exprFour.add("4");
exprFour.add(")");
ArrayList<String> exprFive = new ArrayList<String>();
exprFive.add("120");
exprFive.add("/");
exprFive.add("(");
exprFive.add("10");
exprFive.add("*");
exprFive.add("4");
exprFive.add(")");
ArrayList<String> exprSix = new ArrayList<String>();
exprSix.add("600");
exprSix.add("*");
exprSix.add("2");
exprSix.add("+");
exprSix.add("20");
exprSix.add("/");
exprSix.add("4");
exprSix.add("*");
exprSix.add("(");
exprSix.add("5");
exprSix.add("-");
exprSix.add("3");
exprSix.add(")");
}
#Test
public void test() {
}
}
I was going to put this in the before() method:
ShuntingYard sy = new ShuntingYard(/arraylist here/);
And then in the test, pass the lists to the algorithm. My question is that I think I am going the long way around it, would it be better to have a parameterised annotation and pass those lists as a list of parameters?
and a further question: if a test for any of the ArrayLists passes then I am sure I can execute a subsequent test to the RPNEvaluator evaluate method. I hope I haven't been ambiguous.
Help would be very much appreciated.
I would come at it a little differently. Instead of just creating several sets of test data and calling the same test each time break it up in to something meaningful. Instead of writing one test called test() write several separate tests for each aspect of ShuntingYard. For example:
#Test public void
itDoesntDivideByZero()
{
ArrayList<String> divideByZeroExpression = Arrays.asList("5", "0", "/");
// Add code to call your method with this data here
// Add code to verify your results here
}
#Test public void
itCanAdd()
{
ArrayList<String> simpleAdditionExpression = Arrays.asList("1", "2", "+");
// Add code to call your method with this data here
// Add code to verify your results here
}
and so on. This will make your JUnit output much easier to read. When there's a failure you know that it failed while trying to add, or it failed while trying to evaluate an expression that would cause a divide by zero, etc. Doing it the way you have it in the original you'd only know that it failed in the test() method.
Each of the tests here does 3 things:
Arranges the test data
Performs some action with that data
Asserts that the results of the action are as expected
This Arrange, Assert, Act idiom is very common in automated testing. You may also see it called Given, When, Then as in, "Given these conditions, when I call this method, then I should get this result".
Try to get out of the mindset of writing one test to test an entire class or method. Write a test to test one part of a method. Consider this class:
public class Adder {
public int addOneTo(int someNumber) {
return someNumber + 1;
}
}
You might end up with a test suite that looks like:
#Test public void
itAddsOne()
{
int numberToAddTo = 1;
int result = new Adder().addOneTo(numberToAddTo);
assertEquals("One plus one is two", 2, result);
}
#Test(expected="NullPointerException.class") public void
itChokesOnNulls()
{
new Adder().addOneTo((Integer)null);
}
#Test public void
itDoesntOverflow()
{
int result = new Adder().addOneTo(Integer.MAX_VALUE);
// do whatever here to make sure it worked correctly
}
And so on.
The advise from Mike B is very good, try to separate your test thinking in one test per behavior/functionality.
For make your test more readable i probably write a static constructor for the class ShuntingYard that receives a string, then you can write:
ShuntingYard addition = ShuntingYard.createFromExpresion("2+2");
assertThat(addition.getRpn().evaluate(), is(4));
you can refactor a little more and ends with something like that:
assertThat(evaluate("2+2"), is(4))
That is easy to understand an and easy to read, and in addition write more test with diferent scenarios its one-line of code.
Other option its to write parametrized test, one example: http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/, but in my opinion are really ugly. This test are normally called "data driven test" and are used when you want to test the same code with different input values.
For this data-driven test a much better option its to use something like spock, a groovy framework for testing that allows you to write incredible semantic test, and of course you can use for testing java code, check this out: http://docs.spockframework.org/en/latest/data_driven_testing.html

Categories