I got this code in my junit:
new NonStrictExpectations(mPersonEvaluator) {
{
invoke(mPersonEvaluator, "doEvaluatePerson", withAny(String.class), withAny(Integer.class), withAny(Integer.class));
result = doEvaluatePerson((String)any, (Integer)any, (Integer)any);
}
};
I want to generate the result from my private method doEvaluatePerson((String)any, (Integer)any, (Integer)any); everytime the method doEvaluatePerson is called in the business logic of mPersonEvaluator.
The invoke works fine but the result is only calculated once during the setup of the junit and that result is null.
My question is how can I declare such kind of usecase in jmockit so that the mock uses my private method?
Thank in advance
Stefan
ok I found the answer.
one possible solution is to use a Delegator like this:
result = new Delegate<PersonArt>() {
PersonArt delegator(String pShortName, Integer pOld, Integer pSize)
{
return doEvaluatePersonArt(pShortName, pOld, pSize);
}
};
works pretty fine.
Related
I have this Method that throws an IllegalArgumentException when somebody tries to call it with value 0.
I want to write several stub and mock tests - for example - for the method getFrequentRenterPoints.
I coudn't figure out any "when" or "verify" statements which are used in mocks so I mixed parts of mocks and parts of stubs together and came up with this:
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
//given
Movie movieMock = mock(Movie.class);
//when
movieMock.getFrequentRenterPoints(0);
//then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}
Is it okay to have in a class with other Mocks, or if I want to use assertThrows should I change this into a stub? Or can I use assertThrows with mocks?
The answer from Benjamin Eckardt is correct.
But I try to approach this question from another point of view: when to use mocking? This is one of my favourite answers to that question.
So in practise:
Say your code is like (just guessing all the business objects & names...):
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// this is just the rest of code in which your test does not enter because
// of thrown exception
return somethingToReturn();
}
For this you do not need and you should not want to mock anything here.
But when things get more complicated like your method would be like:
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// What is this?
// It is injected in the Movie - say - like
//
// #Resource
// private RenterPointService renterPointService;
List<RenterPoints> unfiltered = renterPointService.getRenterPoints(renterId);
return filterToFrequent(unfiltered);
}
Now if you test renterId >= 1 what about this renterPointService how do you instantiate it to not get NPE? Say if it is injected and requires to pull up heavy framework for testing or it requires very heavy construction or so? You do not, you mock it.
You are testing the class Movie not the class RenterPointService so you should not bother to think how RenterPointService works but what it returns when used in the class Movie. Still: you do not mock the class Movie which you are testing.
Assuming using you are using Mockito and using annotations the mocking would be then done in your test class like:
#Mock
private RenterPointService renterPointService;
#InjectMocks
private Movie movie;
Then you would do mocking of methods for renterPointService like:
when(renterPointService.getRenterPoints(anyInt))
.thenReturn(someListContaineingMockRenterPointsForThisTest);
Usually you expect the tested production method to throw and not the mock or stub. I drafted it by using new Movie().
Furthermore in that case it does not really make sense to separate the calls into when and then because if movieMock.getFrequentRenterPoints(0); throws, assertThrows(...) will never be executed.
To apply the given/when/then structure with the assertThrows API you could extract the passed lambda in some way, but I personally don't see much benefit in it.
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
// given
Movie movieMock = new Movie();
// when/then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}
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'm doing a mock for this method:
public String buscarDescripcion(MaestroDTO departamento, String codigoMunicipio){
String descripcion = null;
List<MaestroDTO> listaMunicipios = getListaMucipios(departamento);
if(listaMunicipios != null) {
for (MaestroDTO maestroDTO : listaMunicipios) {
if(maestroDTO.getCodigo().equals(codigoMunicipio)){
descripcion = maestroDTO.getNombre();
break;
}
}
}
return descripcion;
}
In a Test class. This return a list full of names of cities.
But when I run the test, I have the NullPointerException error.
The mock that I'm using in the test class is this:
listaCiudad = mock(ListaCiudad.class);
when(listaCiudad.buscarDescripcion(any(MaestroDTO.class), any(BigDecimal.class).toString())).thenReturn("MEDELLIN");
The method buscarDescripcion have two parameters, MaestroDTO and one String. When I run the test using a String, this show me an cast error. And when I'm using a BigDecimal.toString() this show me a nullpointerexception. I don't know if I'm calling in a wrong way this parameters, because I don't know too much about mocks!
I appreciate your help! Thank you! (sorry for my english).
You are not stubbing your mock correctly. You should replace any(BigDecimal.class).toString() with MockitoanyString()
Mockito.when(listaCiudad.buscarDescripcion(Mockito.any(MaestroDTO.class), Mockito.anyString())).thenReturn("MEDELLIN");
I am testing my Java code using EasyMock.
The piece of code that I want to mock looks like this:
requestInfo = mupClient.newEnqueueRequestCall().call(requestArgs);
The way I am mocking this is:
expect(mupClient.newEnqueueRequestCall()).andReturn(enqueueRequestCall);
final Capture<EnqueueRequestArgs> captureRequestArgs =
new Capture<EnqueueRequestArgs>();
expect(mupClient.newEnqueueRequestCall().call(capture(captureRequestArgs))).
andThrow(new MUPCoralException("an exception"));
But requestInfo is always null. Even if I change the .andThrow() part to .andReturn(new RequestInfo()), it is still null.
I checked the other similar post but that did not work. Now was I able to comment on it and hence creating a new question.
ANSWER:
add all mock'd objects in replay! Example replay(mockObj1, mockObj2, ...)
Try this:
expect(mupClient.newEnqueueRequestCall()).andReturn(enqueueRequestCall);
final Capture<EnqueueRequestArgs> captureRequestArgs =
new Capture<EnqueueRequestArgs>();
expect(enqueueRequestCall.call(capture(captureRequestArgs))).
andThrow(new MUPCoralException("an exception"));
The problem is that your enqueRequestCall should return requestInfo. mupClient will return enqueueRequestCall only after you call replay method from easymock.
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;
}
}
};