I have method and need to test it:
void update() {
_cleaner.clear();
_updator.upadate();
}
The ordering of calls is important for this scenario. I want to write test like this:
void updateTest(){
Integer CLEAR = 0, UPDATE = 1;
Stack<Integer> callStack = new Stack<>();
Cleaner cleaner = mock(Cleaner.class);
Updator updator = mock(Updator.class);
when(cleaner.clear()).callback(() -> callStack.add(CLEAR));
when(updator.update()).callback(() -> callStack.add(UPDATE));
Some testingObj = new Some(cleaner, updator);
testingObj.update();
assertEquels(CLEAR, callStack.pop());
assertEquels(UPDATE, callStack.pop());
assertTrue(callStack.isEmpty());
}
_cleaner.clear() and _updator.upadate() returns void. It is clear that
when(cleaner.clear()).callback(() -> callStack.add(ClearCall));
when(updator.update()).callback(() -> callStack.add(UpdateCall));
is invalid code. What can I write except those lines for success? How to setup callback for method (with void as type of result) call by mockito?
I recommend you use the InOrder verifier to confirm that the methods are called in the order you want. See here for some of the documentation: http://site.mockito.org/mockito/docs/current/org/mockito/InOrder.html
This example is based on code straight from that documentation:
InOrder inOrder = inOrder(cleaner, updator);
inOrder.verify(cleaner).clear();
inOrder.verify(updator).update();
Related
Im trying to make an unit test for this method
public void loadProductsFromAPI() {
List<ProductEntity> databaseProducts = productService.getAllProductsFromBd();
CountryTenant.country.forEach((key, value) -> {
List<ProductEntity> productsByCountry = databaseProducts.stream()
.filter(product -> key.toString().equalsIgnoreCase(product.getCountry()))
.collect(Collectors.toList());
List<ProductDTO> productsFromAPI = productsApi.getAllProductsFromAPI(value);
List<ProductEntity> processedProducts = productService.persistProductsFromApi(key, productsByCountry, productsFromAPI);
});
}
My problem its the List<ProcuctEntity> productsByCountry, that variable is created in the execution time. How can I mock that in my test case?
With mockito I already mock my products from db.
Mockito.when(productService.getAllProductsFromBd()).thenReturn(databaseProducts);
If you ever find yourself trying to mock a value, you probably need to clean up your test plan. In this case, the productsByCountry is a value that is calculated inside your method: The correctness of that stream pipeline is part of what you need to verify. Mocking it would simply bypass ensuring that your logic is correct.
Instead, return appropriate test data from the mock productService and ensure that the correct filtered result if passed to persistProducts.
Edit:
Sorry, my example is not very proper, I changed it a little.
I'm not sure if the title shows my question properly.
For example, I have functions:
class Dependency {
// create an element with id and data, add it into a list and return the element
public Element addElement(int id, data d) throws SomeException;
// remove an element from the list and return it
public Element removeElement(int id) throws SomeException;
}
Then I can mock it like:
private Element mockElement(int id, data dt) {
Element e = mock(Element.class);
when(e.getId()).thenReturn(id);
when(e.getData()).thenReturn(dt);
return e;
}
private Dependency mockDependency() {
List l = new List();
Dependency dependency = mock(Dependency.class);
// should I "implement" the internal logic when mocking?
when(dependency.addElement(intCaptor.capture(), dataCapture.capture())).thenAnswer(a->{
int id = intCaptor.getValue();
data dt = dataCaptor.getValue();
if (id < 0) { throw someException; }
Element e = mockElement(id, dt);
l.add(e);
return e;
};
when(dependency.removeElement(intCaptor.capture())).thenAnswer(a->{
int id = intCaptor.getValue();
if (id < 0) { throw someException; }
Element e = l.findElementInListById(id);
if (e == null) { return null; }
l.remove(e);
return e;
};
return dependency;
}
...
#Test
public void test() {
...
Dependency dependencyMock = mockDependency();
MyClass c = new MyClass(dependencyMock);
// it calls dependency.addElement()
c.addElement(1, data)
// it calls dependency.removeElement()
assertEquals(1, c.removeElement(1).getId());
...
}
This does work, but I wonder if it is a good idea to do so. All the examples I can find online about Mockito are basically simple when().then() statements. Can anyone please give me some advice?
The idea of mocking is to test the functionality you have written, the mocks should be only given for the services that are used by the method being tested.
For example, when you test the method public Element addElement(int id, data d) throws SomeException; you should call the original implementation and then you should assert the response that you expect to get for the given input.
Suppose inside addElement method you are internally calling a service myService.processData then you should mock the call to the myService.processData only and the rest of the flow should be as it would have been had the method been called in real scenario.
You should read more on Unit tests, one link I found is here
EDIT
In the example you have given, I think what you have done is, you have put the code inside the original dependency.addElement method inside the mock object you are creating, if you do that you will have to change your test case every time you make a change in the code because once you make a code change in original method dependency.addElement the code in test class becomes out of sync with it and you no longer be testing the feature. Even with this code you are not actually testing the original feature since dependency.addElement is mocked.
The correct approach is to call the original method dependency.addElement with a known input and assert the answer.
I hope this explains it.
I'm making a test for a service with a mock.
The problem is to create and inject instance directly from the class to test.
The source is shown below.
public OrderOutDTO createOrder(OrderSessionDTO orderSessionDTO) {
Order order = orderRepository.save(new Order(orderSessionDTO));
CreateOrderResDTO callServiceOrder = callService.createOrder(new CreateOrderReqDTO(order));
CreateOrderReqDTO createOrderReqDTO = mock(CreateOrderReqDTO.class);
createTrace(order, callServiceOrder.getData().getReceipt().getTransactionHash(), Trace.PUBLIC);
return new OrderOutDTO(order, null);
}
and test source is shown below.
#Test
public void createOrder() {
// given
CallService callService = mock(CallService.class);
CreateOrderResDataDTO createOrderResDataDTO = mock(CreateOrderResDataDTO.class);
// when
when(callService.createOrder(createOrderReqDTO)).thenReturn(createOrderResDTO);
OrderOutDTO order = orderService.createOrder(orderSessionDTO);
// then
assertThat(order, is(Matchers.notNullValue()));
assertThat(order.getOrder(), is(Matchers.notNullValue()));
assertThat(order.getOrder().getReceiver().getName(), is("test"));
}
I thought this test would finish well. But in the code below, it returned null and failed.
// callService.createOrder(new CreateOrderReqDTO(order)) return null
CreateOrderResDTO callServiceOrder = callService.createOrder(new CreateOrderReqDTO(order));
It doesn't seem to recognize it because the service injects a new instance. I want the mock data returned. What should I do?
In the following line you're mocking behavior on createOrderReqDTO as param:
when(callService.createOrder(createOrderReqDTO)).thenReturn(createOrderResDTO);
whereas further, you're passing some other object:
OrderOutDTO order = orderService.createOrder(orderSessionDTO);
This behavior is not recognized, you would have to pass the same thing you mocked before.
I found it myself!
I use argumentMatchers.
when(callService.createOrder(createOrderReqDTO)).thenReturn(createOrderResDTO);
to
when(callService.createOrder(any())).thenReturn(createOrderResDTO);
thank you.
I have the following interface:
public interface Test{
public void block(String modifier);
public boolean blocked(String modifier);
}
So I wanted to mock this interface as follows:
Test m = Mockito.mock(Test.class);
when(m.blocked(Mockito.any()).thenReturn(true);
//I want to mock m.block()
Buty I want to mock Test::block(String) the way so when it is called on some String someString it changes the behavior so that m.blocked(someString) will return false.
Is it possible to do so in Mockito?
You can use thenAnswer and doAnswer to execute arbitrary code when a method is called. For example, you could use a Set to keep track of the strings that have already been blocked:
Set<Object> blocked = new HashSet<>();
Test m = mock(Test.class);
doAnswer(invocation -> blocked.add(invocation.getArguments()[0]))
.when(m).block(any());
when(m.blocked(any()))
.thenAnswer(invocation -> !blocked.contains(invocation.getArguments()[0]));
Here's a sample, assuming you have a boolean field that starts as true --
when(m.blocked(Mockito.any()).thenAnswer(invocation -> this.mockValue);
when(m.block(Mockito.eq("Some String")).thenAnswer(invocation -> {
this.mockValue = false;
return null;
});
Hopefully I didn't get the syntax wrong :-)
I've got a class like the following:
class A
{
public method doSomething()
{
//....
DAO dataAccessor = new DAO();
List<Object> result1 = dataAccessor.getData(dataAccessor.getSql1());
List<Object> result2 = dataAccessor.getData(dataAccessor.getSql2());
//.. do some stuff with the results
}
Now, I use jMockit for testing the above function, by mocking the DAO class.
This is how my test class looks like:
class A_Test
{
private A myAClass;
#Mocked DAO mockedDAO;
List<Object> resultToSql1, resultToSql2;
// ... Some initializations...
#Test
public void testDoSomething()
{
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getData(withEqual("SQL1")); result = resultToSql1;
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
};
myAClass.doSomething();
}
}
Now, it seems that the second expectation regarding getData() masks the first one, i.e. the mock object behaves as if I never declared the first lines in the expectation (the ones that handle sql1):
The first call to getData() returns empty collection, instead of the values with which I initialized resultToSql1. The second call returns resultToSql2, as expected.
If I comment the following line:
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
the first call is returning what I defined - resultToSql1, and the second returns empty collection.
This makes sense.
So, what am I doing wrong? ?How can I define two different return values from getData() based on the parameters of the call?
Any help would be appreciated.
Thanks!
So, After digging more deeply inside the manual, I found that:
...But what if a test needs to decide the result of a recorded invocation based on the arguments it will receive at replay time? We can do it through a mockit.Delegate instance ...
So, in order to solve the above problem, the expectations block should look like this:
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(anyString);
result = new mockit.Delegate()
{
List<Object> getData(String sql)
{
if (sql.equals("SQL1"))
return resultToSql1;
if (sql.equals("SQL2"))
return resultToSql2;
return null;
}
}
};