i have code like below
ScheExeService.ScheduleId scheduleID = ScheExeService.getOneTimeScheduleId(nl.getCompany(), workItem.getId());
ScheExeService.Schedule schedule = ScheExeService.loadSchedule(nl, scheduleID.getId());
Calendar cal = Calendar.getInstance(java.util.TimeZone.getTimeZone(nl.getTimeZone()));
cal.setTime(schedule.attributes.startDate.toDate());
AND i am trying to mock "schedule.attributes.startDate.toDate()"
and ScheExeService look like below
public class ScheExeService implements blah
{
public final static class Schedule {
public final ScheduleId id;
public final ScheduleAttributes attributes;
public final String callableClassName;
public final long itemId;
public Schedule(ScheduleId id, ScheduleAttributes attributes, String callableClassName, long itemId)
{
this.id = id;
this.attributes = attributes;
this.callableClassName = callableClassName;
this.itemId = itemId;
}
}
public final static class ScheduleAttributes {
public final #Nullable LocalDate startDate;
public final #Nullable LocalTime startTime;
public final #Nullable LocalDate endDate;
public final #Nullable LocalTime endTime;
Method code
}
}
and i tried
doNothing().doThrow(new RuntimeException()).when(mockedCalenderObject).setTime(null);
but i am keep getting NPE.
how i can avoid schedule.attributes.startDate.todate() call..?
It's a good idea not to mock data/value objects like List and String, including Joda objects like LocalDate and LocalTime and your data objects like Schedule and ScheduleAttributes. This is mostly because, unless the instances are hard to create, you can just create instances in your test and have the getters and setters behave as expected.
See also: "Test smell: Everything is mocked"
Based on your code, I'd very much suggest mocking loadSchedule (which may require refactoring ScheExeService away from static methods, refactoring the second half of your system under test to accept an arbitrary Schedule, or using PowerMock) and creating your test Schedule using real calls.
public void yourMethod(NL nl, WorkItem workItem) {
ScheExeService.ScheduleId scheduleID = ScheExeService.getOneTimeScheduleId(nl.getCompany(), workItem.getId());
ScheExeService.Schedule schedule = ScheExeService.loadSchedule(nl, scheduleID.getId());
processSchedule(schedule);
}
/**
* Processes schedule for yourMethod. Exposed for testing: Create as many
* arbitrary Schedules as you want and pass them in to test this thoroughly.
*/
void processSchedule(Schedule schedule) {
Calendar cal = Calendar.getInstance(java.util.TimeZone.getTimeZone(nl.getTimeZone()));
cal.setTime(schedule.attributes.startDate.toDate());
// ...
}
Related
Unit test noob here.
I have three classes: Db1Dao, Db2Dao, ExecuteClass where Db1Dao, Db2Dao are database access objects for two different databases. My goal is to fetch some data from db1 using Db1Dao and run executeClass.execute() to "put" the processed data into db2 using Db2Dao.
My ExecuteClass looks like this:
class ExecuteClass {
private Db1Dao db1Dao;
private Db2Dao db2Dao;
public void execute() {
...
List<String> listOfString = getExternalData(someParam);
List<Metadata> metadatum = db1Dao.get(someInputs);
... I do something to generate a list of new class `A` based on listOfString & metadatum ...
try {
db2Dao.put(listOfA);
} catch (PutException e){
...
}
}
public List<String> getExternalData(SomeClass someParam){
... do something
return listOfString;
}
}
Now I want to test:
Given a specific listOfString (returned by getExternalData) and a specific metadatum (returned by db1Dao.get):
Will I get the desired listOfA?
Am I able to call db2Dao.put and its input parameter is listOfA?
Particularly, I have hard-coded sample listOfString and metadatum and desired listOfA (and they will be passed via an object MockData, see the following code) but I don't know how to write the test using Mockito. The following is a test class I wrote but it does not work:
class TestClass extends BaseTest {
#Mock
private Db1Dao db1Dao;
#Mock
private Db2Dao db2Dao;
private ExecuteClass executeClass;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
executeClass = new ExecuteClass(db1Dao, db2Dao);
}
#ParameterizedTest
#MethodSource("MockDataProvider")
public void executeClassTest(final MockData mockData) throws PutException {
Mockito.when(db1Dao.get(Mockito.any(), ...))
.thenReturn(mockData.getMetadatum());
ExecuteClass executeClassSpy = Mockito.spy(executeClass);
Mockito.when(executeClassSpy.getExternalData(Mockito.any()))
.thenReturn(mockData.getListOfString());
executeClassSpy.execute();
// executeClass.execute(); not working neither...
List<A> listOfA = mockData.getDesiredListOfA();
Mockito.verify(db2Dao).put(listOfA);
}
}
Could anyone please let me know? Thank you in advance!!
You should not create a spy of the same class you want to test. Instead, try to write a unit test for the smallest amount of code (e.g. a public method) and mock every external operator (in your case Db1Dao and Db2Dao).
If testing a public method involves calling another public method of the same class, make sure to mock everything inside the other public method (in your case getExternalData). Otherwise, this other public method might be a good candidate for an extra class to have clear separation of concerns.
So, remove the ExecuteClass executeClassSpy = Mockito.spy(executeClass); and make sure you setup everything with Mockito what's called within getExternalData.
To now actually, verify that Db2Dao was called with the correct parameter, either use your current approach with verifying the payload. But here it's important to 100% create the same data structure you get while executing your application code.
Another solution would be to use Mockito's #Captor. This allows you to capture the value of why verifying the invocation of a mock. Later on, you can also write assertions on the captured value:
#Captor
private ArgumentCaptor<ClassOfListOfA> argumentCaptor;
#Test
public void yourTest() {
Mockito.verify(db2Dao).put(argumentCaptor.capture());
assertEquals("StringValue", argumentCaptur.getValue().getWhateverGetterYouHave);
}
The following code worked for me.
I partially accepted #rieckpil's answer. I used #Captor which is very handy.
The reason I had to mock getExternalData() is because its implementation is still a "TODO".
class TestClass extends BaseTest {
#Mock
private Db1Dao db1Dao;
#Mock
private Db2Dao db2Dao;
#Captor
private ArgumentCaptor<List<A>> argumentCaptor;
private ExecuteClass executeClass;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
executeClass = new ExecuteClass(db1Dao, db2Dao);
}
#ParameterizedTest
#MethodSource("MockDataProvider")
public void executeClassTest(final MockData mockData) throws PutException {
Mockito.when(db1Dao.get(Mockito.any(), ...))
.thenReturn(mockData.getMetadatum());
ExecuteClass executeClassSpy = Mockito.spy(executeClass);
Mockito.when(executeClassSpy.getExternalData(Mockito.any()))
.thenReturn(mockData.getListOfString());
executeClassSpy.execute();
List<A> listOfA = mockData.getDesiredListOfA();
Mockito.verify(db2Dao).put(argumentCaptor.capture());
assertEquals(listOfA, argumentCaptor.getValue());
}
}
Please find the below code for the DAO & Entity Object and Accessor
#Table(name = "Employee")
public class Employee {
#PartitionKey
#Column(name = "empname")
private String empname;
#ClusteringColumn(0)
#Column(name = "country")
private String country;
#Column(name = "status")
private String status;
}
Accessor:
#Accessor
public interface EmployeeAccessor {
#Query(value = "SELECT DISTINCT empname FROM EMPLOYEE ")
ResultSet getAllEmployeeName();
}
}
DAO getAllEmployeeNames returns a List which are employee names
and it will be sorted in ascending order.
DAO
public class EmployeeDAOImpl implements EmployeeDAO {
private EmployeeAccessor employeeAccessor;
#PostConstruct
public void init() {
employeeAccessor = datastaxCassandraTemplate.getAccessor(EmployeeAccessor.class);
}
#Override
public List<String> getAllEmployeeNames() {
List<Row> names = employeeAccessor.getAllEmployeeName().all();
List<String> empnames = names.stream()
.map(name -> name.getString("empname")).collect(Collectors.toList());
empnames.sort(naturalOrder()); //sorted
return empnames;
}
}
JUnit Test(mockito):
I am not able to mock the List[datastax row]. How to mock and returns a list of rows with values "foo" and "bar".Please help me in unit test this.
#Category(UnitTest.class)
#RunWith(MockitoJUnitRunner.class)
public class EmployeeDAOImplUnitTest {
#Mock
private ResultSet resultSet;
#Mock
private EmployeeAccessor empAccessor;
//here is the problem....how to mock the List<Row> Object --> com.datastax.driver.core.Row (interface)
//this code will result in compilation error as we are mapping a List<Row> to the ArrayList<String>
//how to mock the List<Row> with a list of String row object
private List<Row> unSortedTemplateNames = new ArrayList() {
{
add("foo");
add("bar");
}
};
//this is a test case to check if the results are sorted or not
//mock the accessor and send rows as "foo" & "bar"
//after calling the dao , the first element must be "bar" and not "foo"
#Test
public void shouldReturnSorted_getAllTemplateNames() {
when(empAccessor.getAllEmployeeName()).thenReturn(resultSet);
when(resultSet.all()).thenReturn(unSortedTemplateNames); //how to mock the List<Row> object ???
//i am testing if the results are sorted, first element should not be foo
assertThat(countryTemplates.get(0), is("bar"));
}
}
Wow! This is overly complex, hard to follow, and not an ideal way to write unit tests.
Using PowerMock(ito) along with "static" references in your own code is not recommended and is a sure sign of a code smells.
First, I am not sure why you decided to use a static reference (e.g. EmployeeAccessor.getAllEmployeeName().all(); inside the EmployeeDAOImpl class, getAllEmployeeNames() method) instead of using the instance variable (i.e. empAccessor), which is more conducive to actual "unit testing"?
The EmployeeAccessor, getAllEmployeeName() "interface" method is not static (clearly). However, seemingly, whatever this (datastaxCassandraTemplate.getAccessor(EmployeeAccessor.class);) generates makes it so (really?), which then requires the use of PowerMock(ito), o.O
Frameworks like PowerMock, and extensions of (i.e. "PowerMockito"), were meant to test and mock code used by your application (unfortunately, but necessarily so) where this "other" code makes use of statics, Singletons, private methods and so on. This anti-pattern really ought not be followed in your own application design.
Second, it is not really apparent what the "Subject Under Test" (SUT) is in your test case. You implemented a test class (i.e. EmployeeDAOImplTest) for, supposedly, your EmployeeDAOImpl class (the actual "SUT"), but inside your test case (i.e. shouldReturnSorted_getAllTemplateNames()), you are calling... countryLocalizationDAOImpl.getAllTemplateNames(); thus testing the CountryLocalizationDAOImpl class (??), which is not the "SUT" of the EmployeeDAOImplTest class.
Additionally, it is not apparent that the EmployeeDAOImpl even uses a CountryLocalizationDAO instance (assuming an interface here as well), and if it does, then it is certainly something that should be "mocked" when the EmployeeDAOImpl "interacts" with instances of CountryLocalizationDAO, particularly in the context of a unit test. The only correlation between the EmployeeDAO and CountryLocalizationDAO is that the Employee has a country field.
There are a few other problems with your design/setup as well, but anyway.
Here are a few suggestions...
First, let's test what your EmployeeDAOImplTest is meant to test... EmployeeDAO.getAllEmployeeNames() in a sorted fashion. This in turn may give you ideas of how to test your "CountryLocalizationDAO, getAllTemplateNames() method perhaps (if it even makes sense, i.e. getAllTemplateNames() is in fact dependent on an Employee's country, when Employees are ordered by name (i.e. "empname" and accessed via EmployeeAccessor).
public class EmployeeDAOImpl implements EmployeeDAO {
private final EmployeeAccessor employeeAccessor;
// where does the DataStaxCassandraTemplate reference come from?!
private DataStaxCassadraTemplate datastaxCassandraTemplate = ...;
public EmployeeDAOImpl() {
this(datastaxCassandraTemplate.getAccessor(EmployeeAccessor.class));
}
public EmployeeDAOImpl(EmployeeAccessor employeeAccessor) {
this.employeeAccessor = employeeAccessor;
}
protected EmployeeAccessor getEmployeeAccessor() {
return this.empAccessor;
}
public List<String> getAllEployeeNames() {
List<Row> nameRows = getEmployeeAccessor().getAllEmployeeName().all();
...
}
}
Then in your test class...
public class EmployeeDAOImplUnitTest {
#Mock
private EmployeeAccessor mockEmployeeAccessor;
// SUT
private EmployeeDAO employeeDao;
#Before
public void setup() {
employeeDao = new EmployeeDAOImpl(mockEmployeeAccessor);
}
protected ResultSet mockResultSet(Row... rows) {
ResultSet mockResultSet = mock(ResultSet.class);
when(mockResultSet.all()).thenReturn(Arrays.asList(rows));
return mockResultSet;
}
protected Row mockRow(String employeeName) {
Row mockRow = mock(Row.class, employeeName);
when(mockRow.getString(eq("empname")).thenReturn(employeeName);
return mockRow;
}
#Test
public void getAllEmployeeNamesReturnsSortListOfNames() {
when(mockEmployeeAccessor.getAllEmployeeName())
.thenReturn(mockResultSet(mockRow("jonDoe"), mockRow("janeDoe")));
assertThat(employeeDao.getAllEmployeeNames())
.contains("janeDoe", "jonDoe");
verify(mockEmployeeAccessor, times(1)).getAllEmployeeName();
}
}
Now, you can apply similar techniques if in fact there is an actual correlation between Employees and CountryLocalizationDAO via the EmployeeAccessor.
Hope this helps get you on a better track!
-j
QueueItems[] items = ....
how i can mock object for QueueItems[] using mockito?
i tried : ArrayList workItems = mock(ArrayList.class);
QueueItems = mock(QueueItems.class);
but not working.
If you want to customly create an array of items, you should create such an array and then insert mocks into the array. You should not try to mock an array, as this is core Java implementation.
Also, Lists are better to use as they allow more flexibility. An example:
#RunWith(MockitoJUnitRunner.class)
public class TestClass {
#Mock
private QueueItem item1;
private List<QueueItem> items;
#Before
public void setUp() {
items = new ArrayList<QueueItem>();
// Your mocked QueueItem is the first entry in the list
items.add(item1);
}
#Test
public void simpleTest() {
invokeSomeMethodWithList(items);
Mockito.verify(item1).someMethod();
}
}
Disclaimer: I'm completely new to Event Sourcing, Axon Framework and DDD, so there is quite big possibility I'm doing something wrong.
I'm doing an application to manage events - conferences, workshops etc.
I have one aggregate root, which is EventProposal. There should be a possibility to assign a TodoList to given EventProposal. TodoList is another aggregate root, consisting of TodoItems - entities. TodoItem can be edited, mark as done etc.
There is a requirement of assigning TodoItem to TodoList, which I've implemented this way:
public class TodoList extends AbstractAnnotatedAggregateRoot {
#AggregateIdentifier
private TodoListId id;
#EventSourcedMember
private List<TodoItem> todoItems = Lists.newArrayList();
...
public void assignTodoItem(TodoItemId todoItemId, String content, LocalDate creationDate) {
if (alreadyHasTodoItemWith(todoItemId)) {
apply(new TodoItemNotAssignedToTodoList(
id, todoItemId)
);
return;
}
apply(new TodoItemAssignedToTodoListEvent(
id, todoItemId, content, creationDate)
);
}
#EventSourcingHandler
public void on(TodoItemAssignedToTodoListEvent event) {
final TodoItem item = TodoItemFactory.create(
event.todoItemId(),
event.description(),
event.createdAt()
);
todoItems.add(item);
}
Corresponding success-path command and event:
#Value
#Accessors(fluent = true)
public class AssignTodoItemToTodoListCommand {
#TargetAggregateIdentifier
private final TodoListId todoListId;
private final TodoItemId todoItemId;
private final String description;
private final LocalDate createdAt;
}
#Value
#Accessors(fluent = true)
public class TodoItemAssignedToTodoListEvent {
private final TodoListId todoListId;
private final TodoItemId todoItemId;
private final String description;
private final LocalDate createdAt;
}
This could be easly tested with Axon's BDD-way. (GivenThenFixture)
But now - there is another requirement: one should be able to create TodoList upon existing TodoListTemplate. Template is just an aggregate that wrapps a collection of TodoItemTemplates.
And there comes my implementation problem. I tried something like (in TodoList class):
public void fulfillWith(TodoListTemplate todoListTemplate, LocalDate creationDate) {
if (alreadyHasAnyTodoItem()) {
apply(new TodoListNotFulfilledWithTemplateEvent(
id,
todoListTemplate.id()
)
);
return;
}
apply(new TodoListFulfilledWithTemplateEvent(
id,
todoListTemplate.id(),
todoListTemplate.todoItemDescriptions(),
creationDate
)
);
}
#EventSourcingHandler
public void on(TodoListFulfilledWithTemplateEvent event) {
todoItems.addAll(
fromDescriptions(event.todoItemDescriptions(), event.fulfilledAt())
);
}
private Collection<TodoItem> fromDescriptions(Collection<String> descriptions, LocalDate creationDate) {
return descriptions.stream()
.map(description -> TodoItemFactory.create(description, creationDate))
.collect(Collectors.toList());
}
Again, commands and events:
#Value
#Accessors(fluent = true)
public class FulfillTodoListWithTemplateCommand {
private final TodoListId todoListId;
private final TodoListTemplateId todoListTemplateId;
private final LocalDate creationDate;
}
#Value
#Accessors(fluent = true)
public class TodoListFulfilledWithTemplateEvent {
private final TodoListId todoListId;
private final TodoListTemplateId todoListTemplateId;
private final List<String> todoItemDescriptions;
private final LocalDate fulfilledAt;
}
Problem:
As you can see - there is TodoItemFactory class involved, generating an unique ID:
public static TodoItem create(String content, LocalDate createdAt) {
return TodoItemFactory.create(nextId(), content, createdAt);
}
This way it can't be tested with axon - it gives me error org.axonframework.test.AxonAssertionError: Illegal state change detected!
This is quite obvious - working aggregate's ID is different than the one's constructed after aplying events.
Finally, my question arrives:
How should I solve this?
Generate those IDs somewhere and include them in outcoming TodoListFulfilledWithTemplateEvent? This leads to having two collections in an event - one for IDs, one for item contents/descriptions.
Assume that I got those IDs generated before and include them not only in outcoming Event, but also in incoming Command. This leads to same ugliness as before, but twice.
Do it in the way that I invoke 'assingTodoItemToTodoList' method multiple times, which will generate a lot of events and could produce reordering as events are async.
Sorry for verboseness, I tried to be as specific as possible.
Does anyone have idea about writing unit test case for ATG using Mockito? I came across following discussions while goggling -
Automated unit tests for ATG development and
Using PowerMock to obtain the ATG Nucleus in testing results in NPE
But need a help in setting up Nucleus and other dependencies (DAS, DPS, DSS etc.) and a sample test class for droplet using Mockito.
We are using ATG Dust where we have to set all the dependencies. I am wondering if we can replace ATG Dust completely with Mockito. Here is the example how we are writing the test cases -
A Base class for setting Nucleus -
package com.ebiz.market.support;
import java.io.File;
import java.util.Arrays;
import atg.nucleus.NucleusTestUtils;
import atg.test.AtgDustCase;
import atg.test.util.FileUtil;
public class BaseTestCase extends AtgDustCase {
public atg.nucleus.Nucleus mNucleus = null;
private final String ATGHOME="C://ATG/ATG9.4//home";
private final String ATGHOMEPROPERTY = "atg.dynamo.home";
protected void setUp() throws Exception {
super.setUp();
String dynamoHome = System.getProperty(ATGHOMEPROPERTY);
if(dynamoHome == null)
System.setProperty(ATGHOMEPROPERTY, ATGHOME);
File configpath = NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
FileUtil.copyDirectory("src/test/resources/config/test/", configpath.getAbsolutePath(), Arrays.asList(new String [] {".svn"}));
copyConfigurationFiles(new String[]{"config"}, configpath.getAbsolutePath(), ".svn");
}
public File getConfigPath() {
return NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
}
}
Writing the test case by extending the base class -
public class BizDropletTest extends BaseTestCase {
private BizDroplet bizDroplet;
#Before
public void setUp() throws Exception {
super.setUp();
mNucleus = NucleusTestUtils.startNucleusWithModules(new String[] { "DSS", "DPS", "DAFEAR" }, this.getClass(),
this.getClass().getName(), "com/ebiz/market/support/droplet/BizDroplet");
autoSuggestDroplet = (AutoSuggestDroplet) mNucleus.resolveName("com/ebiz/market/support/droplet/BizDroplet");
try {
bizDroplet.doStartService();
} catch (ServiceException e) {
fail(e.getMessage());
}
}
/**
Other methods
*/
}
So, how Mockito can handle these? Again, for me the target is to replace ATG Dust with Mockito completely because ATG Dust take lot of time in running tests due to huge dependencies.
Thanks.
Using Mockito you don't setup Nucleus or other dependencies (unless you need it). You simply mock the objects that you need to use.
Consider a simple class ProductUrlDroplet that retrieves a product from the repository and then outputs a url based on this. The service method would look something like this:
public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {
Object product = pRequest.getObjectParameter(PRODUCT_ID);
RepositoryItem productItem = (RepositoryItem) product;
String generatedUrl = generateProductUrl(pRequest, productItem.getRepositoryId());
pRequest.setParameter(PRODUCT_URL_ID, generatedUrl);
pRequest.serviceParameter(OPARAM_OUTPUT, pRequest, pResponse);
}
private String generateProductUrl(DynamoHttpServletRequest request, String productId) {
HttpServletRequest originatingRequest = (HttpServletRequest) request.resolveName("/OriginatingRequest");
String contextroot = originatingRequest.getContextPath();
return contextroot + "/browse/product.jsp?productId=" + productId;
}
A simple test class for this will then be:
public class ProductUrlDropletTest {
#InjectMocks private ProductUrlDroplet testObj;
#Mock private DynamoHttpServletRequest requestMock;
#Mock private DynamoHttpServletResponse responseMock;
#Mock private RepositoryItem productRepositoryItemMock;
#BeforeMethod(groups = { "unit" })
public void setup() throws Exception {
testObj = new ProductUrlDroplet();
MockitoAnnotations.initMocks(this);
Mockito.when(productRepositoryItemMock.getRepositoryId()).thenReturn("50302372");
}
#Test(groups = { "unit" })
public void testProductURL() throws Exception {
Mockito.when(requestMock.getObjectParameter(ProductUrlDroplet.PRODUCT_ID)).thenReturn(productRepositoryItemMock);
testObj.service(requestMock, responseMock);
ArgumentCaptor<String> argumentProductURL = ArgumentCaptor.forClass(String.class);
Mockito.verify(requestMock).setParameter(Matchers.eq(ProductUrlDroplet.PRODUCT_URL_ID), argumentProductURL.capture());
Assert.assertTrue(argumentProductURL.getValue().equals("/browse/product.jsp?productId=50302372"));
}
}
The key components are that you need to initialise the class you want to test (testObj). You then simply construct the response for each of the input parameters of the objects you are going to use (in this case productRepositoryItemMock represents the RepositoryItem and productRepositoryItemMock.getRepositoryId() returns a String that you can then test against later).
You will also notice that this test only validates the service method and not the individual methods. How you do it is up to you but generally I've been focused on testing my service and handleXXX methods in the formhandlers and droplets.
Testing the XXXManager, XXXUtil and XXXService classes will all have their own tests and should be 'mocked' into the droplets and formhandlers. For these I would write tests for each method though.
PowerMockito only really comes into the picture when you need to mock static methods and classes and the documentation does enough to explain that.