com.devicehive.service.DeviceNotificationServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for com.devicehive.service.DeviceNotificationServiceTest.java

Source

package com.devicehive.service;

/*
 * #%L
 * DeviceHive Frontend Logic
 * %%
 * Copyright (C) 2016 DataArt
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.devicehive.base.AbstractResourceTest;
import com.devicehive.base.RequestDispatcherProxy;
import com.devicehive.configuration.Constants;
import com.devicehive.dao.DeviceDao;
import com.devicehive.model.DeviceNotification;
import com.devicehive.model.JsonStringWrapper;
import com.devicehive.model.SpecialNotifications;
import com.devicehive.model.rpc.*;
import com.devicehive.service.exception.BackendException;
import com.devicehive.shim.api.Request;
import com.devicehive.shim.api.Response;
import com.devicehive.shim.api.server.RequestHandler;
import com.devicehive.vo.DeviceVO;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.Whitebox;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@SuppressWarnings("unchecked")
public class DeviceNotificationServiceTest extends AbstractResourceTest {

    @Autowired
    private DeviceNotificationService notificationService;

    @Autowired
    private RequestDispatcherProxy requestDispatcherProxy;

    @Mock
    private RequestHandler requestHandler;

    private ArgumentCaptor<Request> argument = ArgumentCaptor.forClass(Request.class);

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        requestDispatcherProxy.setRequestHandler(requestHandler);
    }

    @After
    public void tearDown() {
        Mockito.reset(requestHandler);
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testFindOneWithResponse() throws Exception {
        final String guid = UUID.randomUUID().toString();
        final long id = System.currentTimeMillis();
        final String notification = "Expected notification";
        final Date timestamp = new Date();
        final String parameters = "{\"param1\":\"value1\",\"param2\":\"value2\"}";

        final DeviceNotification deviceNotification = new DeviceNotification();
        deviceNotification.setId(id);
        deviceNotification.setDeviceGuid(guid);
        deviceNotification.setNotification(notification);
        deviceNotification.setTimestamp(timestamp);
        deviceNotification.setParameters(new JsonStringWrapper(parameters));

        // return response for any request
        when(requestHandler.handle(any(Request.class))).thenReturn(Response.newBuilder()
                .withBody(new NotificationSearchResponse(Collections.singletonList(deviceNotification)))
                .buildSuccess());

        // call service method
        notificationService.findOne(id, guid).thenAccept(opt -> {
            assertTrue(opt.isPresent());
            assertEquals(guid, opt.get().getDeviceGuid());
            assertEquals(timestamp, opt.get().getTimestamp());
            assertEquals(parameters, opt.get().getParameters().getJsonString());
            assertEquals(notification, opt.get().getNotification());
            assertEquals(Long.valueOf(id), opt.get().getId());
        }).exceptionally(ex -> {
            fail(ex.toString());
            return null;
        }).get(15, TimeUnit.SECONDS);

        verify(requestHandler, times(1)).handle(argument.capture());
        assertEquals(Action.NOTIFICATION_SEARCH_REQUEST.name(), argument.getValue().getBody().getAction());

        NotificationSearchRequest request = argument.getValue().getBody().cast(NotificationSearchRequest.class);
        assertEquals(id, request.getId().longValue());
        assertEquals(guid, request.getGuid());
        assertNull(request.getStatus());
        assertNull(request.getNames());
        assertNull(request.getTimestampStart());
        assertNull(request.getTimestampEnd());
        assertNull(request.getTimestampEnd());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testFindOneWithEmptyResponse() throws Exception {
        final String guid = UUID.randomUUID().toString();
        final long id = System.currentTimeMillis();

        // return empty response for any request
        when(requestHandler.handle(any(Request.class))).thenReturn(Response.newBuilder()
                .withBody(new NotificationSearchResponse(Collections.emptyList())).buildSuccess());

        // call service method
        notificationService.findOne(id, guid).thenAccept(opt -> assertFalse(opt.isPresent())).exceptionally(ex -> {
            fail(ex.toString());
            return null;
        }).get(15, TimeUnit.SECONDS);

        verify(requestHandler, times(1)).handle(argument.capture());
        assertEquals(Action.NOTIFICATION_SEARCH_REQUEST.name(), argument.getValue().getBody().getAction());

        NotificationSearchRequest request = argument.getValue().getBody().cast(NotificationSearchRequest.class);
        assertEquals(id, request.getId().longValue());
        assertEquals(guid, request.getGuid());
        assertNull(request.getStatus());
        assertNull(request.getNames());
        assertNull(request.getTimestampStart());
        assertNull(request.getTimestampEnd());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testFindOneWithErrorResponse() throws Exception {
        final String guid = UUID.randomUUID().toString();
        final long id = System.currentTimeMillis();
        final String expectedErrorMessage = "EXPECTED ERROR MESSAGE";
        final int errorCode = 500;

        // return fail response for any request
        when(requestHandler.handle(any(Request.class))).thenReturn(
                Response.newBuilder().withBody(new ErrorResponse(expectedErrorMessage)).buildFailed(errorCode));

        // call service method
        notificationService.findOne(id, guid).thenAccept(opt -> fail("Must be completed exceptionally"))
                .exceptionally(ex -> {
                    assertEquals(BackendException.class, ex.getCause().getClass());
                    assertEquals(expectedErrorMessage, ex.getCause().getMessage());
                    assertEquals(errorCode, ((BackendException) ex.getCause()).getErrorCode());
                    return null;
                }).get(15, TimeUnit.SECONDS);

        verify(requestHandler, times(1)).handle(argument.capture());
        assertEquals(Action.NOTIFICATION_SEARCH_REQUEST.name(), argument.getValue().getBody().getAction());

        NotificationSearchRequest request = argument.getValue().getBody().cast(NotificationSearchRequest.class);
        assertEquals(id, request.getId().longValue());
        assertEquals(guid, request.getGuid());
        assertNull(request.getStatus());
        assertNull(request.getNames());
        assertNull(request.getTimestampStart());
        assertNull(request.getTimestampEnd());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testFindWithEmptyResponse() throws Exception {
        final List<String> guids = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID().toString())
                .collect(Collectors.toList());
        final Date timestampSt = new Date();
        final Date timestampEnd = new Date();

        final Set<String> guidsForSearch = new HashSet<>(Arrays.asList(guids.get(0), guids.get(2), guids.get(3)));

        // return empty response for any request
        when(requestHandler.handle(any(Request.class))).thenReturn(Response.newBuilder()
                .withBody(new NotificationSearchResponse(Collections.emptyList())).buildSuccess());

        notificationService.find(guidsForSearch, Collections.emptySet(), timestampSt, timestampEnd)
                .thenAccept(notifications -> assertTrue(notifications.isEmpty())).exceptionally(ex -> {
                    fail(ex.toString());
                    return null;
                }).get(15, TimeUnit.SECONDS);

        verify(requestHandler, times(3)).handle(argument.capture());

        NotificationSearchRequest request = argument.getValue().getBody().cast(NotificationSearchRequest.class);
        assertNull(request.getId());
        assertTrue(guidsForSearch.contains(request.getGuid()));
        assertTrue(request.getNames().isEmpty());
        assertEquals(timestampSt, request.getTimestampStart());
        assertEquals(timestampEnd, request.getTimestampEnd());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testFindWithResponse() throws Exception {
        final List<String> guids = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID().toString())
                .collect(Collectors.toList());
        final Date timestampSt = new Date();
        final Date timestampEnd = new Date();
        final String parameters = "{\"param1\":\"value1\",\"param2\":\"value2\"}";

        final Set<String> guidsForSearch = new HashSet<>(Arrays.asList(guids.get(0), guids.get(2), guids.get(3)));

        // return response for any request
        Map<String, DeviceNotification> notificationMap = guidsForSearch.stream()
                .collect(Collectors.toMap(Function.identity(), guid -> {
                    DeviceNotification notification = new DeviceNotification();
                    notification.setId(System.nanoTime());
                    notification.setDeviceGuid(guid);
                    notification.setNotification(RandomStringUtils.randomAlphabetic(10));
                    notification.setTimestamp(new Date());
                    notification.setParameters(new JsonStringWrapper(parameters));
                    return notification;
                }));

        when(requestHandler.handle(any(Request.class))).then(invocation -> {
            Request request = invocation.getArgumentAt(0, Request.class);
            String guid = request.getBody().cast(NotificationSearchRequest.class).getGuid();
            return Response.newBuilder()
                    .withBody(new NotificationSearchResponse(Collections.singletonList(notificationMap.get(guid))))
                    .buildSuccess();
        });

        notificationService.find(guidsForSearch, Collections.emptySet(), timestampSt, timestampEnd)
                .thenAccept(notifications -> {
                    assertEquals(3, notifications.size());
                    assertEquals(new HashSet<>(notificationMap.values()), new HashSet<>(notifications)); // using HashSet to ignore order
                }).exceptionally(ex -> {
                    fail(ex.toString());
                    return null;
                }).get(30, TimeUnit.SECONDS);

        verify(requestHandler, times(3)).handle(argument.capture());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testSubmitDeviceNotificationShouldInsertSingleNotification() throws Exception {
        final DeviceVO deviceVO = new DeviceVO();
        deviceVO.setId(System.nanoTime());
        deviceVO.setGuid(UUID.randomUUID().toString());

        final DeviceNotification deviceNotification = new DeviceNotification();
        deviceNotification.setId(System.nanoTime());
        deviceNotification.setTimestamp(new Date());
        deviceNotification.setNotification(RandomStringUtils.randomAlphabetic(10));
        deviceNotification.setDeviceGuid(deviceVO.getGuid());

        when(requestHandler.handle(any(Request.class))).thenReturn(
                Response.newBuilder().withBody(new NotificationInsertResponse(deviceNotification)).buildSuccess());

        notificationService.insert(deviceNotification, deviceVO)
                .thenAccept(notification -> assertEquals(deviceNotification, notification)).exceptionally(ex -> {
                    fail(ex.toString());
                    return null;
                }).get(15, TimeUnit.SECONDS);

        verify(requestHandler, times(1)).handle(argument.capture());

        NotificationInsertRequest request = argument.getValue().getBody().cast(NotificationInsertRequest.class);
        assertEquals(Action.NOTIFICATION_INSERT_REQUEST.name(), request.getAction());
        assertEquals(deviceNotification, request.getDeviceNotification());
    }

    @Test
    @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
    public void testSubmitDeviceNotificationWithRefreshEquipmentShouldInsertSingleNotification() throws Exception {
        // mock DeviceDao
        final DeviceEquipmentService equipmentServiceMock = Mockito.mock(DeviceEquipmentService.class);
        Whitebox.setInternalState(notificationService, "deviceEquipmentService", equipmentServiceMock);

        // create inputs
        final DeviceVO deviceVO = new DeviceVO();
        deviceVO.setId(System.nanoTime());
        deviceVO.setGuid(UUID.randomUUID().toString());

        final DeviceNotification deviceNotification = new DeviceNotification();
        deviceNotification.setId(System.nanoTime());
        deviceNotification.setTimestamp(new Date());
        deviceNotification.setNotification(SpecialNotifications.EQUIPMENT);
        deviceNotification.setDeviceGuid(deviceVO.getGuid());

        // define returns
        when(requestHandler.handle(any(Request.class))).thenReturn(
                Response.newBuilder().withBody(new NotificationInsertResponse(deviceNotification)).buildSuccess());

        // execute
        notificationService.insert(deviceNotification, deviceVO)
                .thenAccept(notification -> assertEquals(deviceNotification, notification)).exceptionally(ex -> {
                    fail(ex.toString());
                    return null;
                }).get(15, TimeUnit.SECONDS);

        // check
        verify(requestHandler, times(1)).handle(argument.capture());
        verify(equipmentServiceMock, times(1)).refreshDeviceEquipment(eq(deviceNotification), eq(deviceVO));

        NotificationInsertRequest request = argument.getValue().getBody().cast(NotificationInsertRequest.class);
        assertEquals(Action.NOTIFICATION_INSERT_REQUEST.name(), request.getAction());
        assertEquals(deviceNotification, request.getDeviceNotification());
    }
}