ip696
ip696

Reputation: 7084

How can I create unit test for void method which just change data and save it

I have some handler(in this example I just use controller):

@RestController
public class MessageController {

    private final TaskExecutor taskExecutor;
    private final Operation operation;
    private final MessageLogService messageLogService;

    public MessageController(TaskExecutor taskExecutor, Operation operation, MessageLogService messageLogService) {
        this.taskExecutor = taskExecutor;
        this.operation = operation;
        this.messageLogService = messageLogService;
    }

    @PostMapping(value = "/process")
    public String handleMessage(MessageRequest messageRequest){

        MessageLog messageLog = messageLogService.createNewMessageLog();

        taskExecutor.execute(() -> {
            try {
                operation.process(messageLog.getGuid(), messageRequest);
            } catch (MessageLogDoesNotExistException e) {
                throw new RuntimeException(e);
            }
        });
        return "REQUEST_QUOTED";
    }
}
  1. I receive some request.
  2. I create new MessageLog in DB with status "NEW" and some default(and some data from the request in the real project) values and save.
  3. I send messageRequest and MessageLog's guid to the operation in the executor and return sync response "REQUEST_QUOTED" immediately.

@Service
public class MessageOperation implements Operation {

        private final MessageLogService messageLogService;

        public MessageOperation(MessageLogService messageLogService) {
            this.messageLogService = messageLogService;
        }

        @Transactional
        @Override
        public void process(String guid, MessageRequest messageRequest) throws MessageLogDoesNotExistException {

            MessageLog messageLog = messageLogService.getOne(guid);

            if (messageLog == null)
                throw new MessageLogDoesNotExistException();

            try {
                Message message = createMessage(messageRequest);
                messageLog.setStatus("SUCCESS");
                messageLog.setMessage(message);
            } catch (MessageCreationException e) {
                messageLog.setStatus("FAIL");
                messageLog.setErrorCode(e.getCode());
            }
            messageLogService.save(messageLog);
        }

        private Message createMessage(MessageRequest messageRequest) throws MessageCreationException {
            //logic
            return null;
        }
    }

Into operation I create the message and bind it with messageLog. If I create and bind success - I set status 'SUCCESS' or 'FAIL' if not. And just save messageLog.

How can I create Unit test for operation's method process? It is void.

1) I get a request from the client

2) delegate the request to the new thread for the async process

3) return sync response.

And I don't understand how can I create a unit test for public void process(String guid, MessageRequest messageRequest)

Upvotes: 0

Views: 81

Answers (1)

allu
allu

Reputation: 381

In this case for MessageOperation I recommend using Mockito https://www.baeldung.com/mockito-annotations library for mocking the class attribute

@Mock
private final MessageLogService messageLogService;

Then in your unit test you use the verify()method to check that expected behaviour has happened. (save is called correctly for example).

I would also mock the response of getOne to fit your need

MessageLog messageLog = messageLogService.getOne(guid);

for example

MessageLog messageLog = new MessageLog();
when(messageLogService.getOne(eq("THE GUID YOU GIVE IN THE METHDO CALL"))).thenReturn(messageLog);

That way since you have the object reference to MessageLogyou can check for the status in the test code:

assertEquals("SUCCESS", messageLog.getStatus());

And use verify to check that the save method is called correctly:

verify(messageLogService).save(same(messageLog));

About the matchers I used https://www.baeldung.com/mockito-argument-matchers

Upvotes: 1

Related Questions