Невозможно смоделировать или обойти статический метод, используя Mockito / JMockit / Deencapsulation - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь добавить контрольные примеры, используя Mockito.Но внутри этого метода есть вызов статического метода, который возвращает ноль в соответствии с его логикой, и я не могу смоделировать его поведение, так как это статический метод.Мне нужно или насмехаться над этим или обходить это как-то.

Я прошел через аналогичные ссылки в переполнении стека, но не смог решить мою проблему, возможно, потому что некоторые из опрошенных были заданы несколько лет назад, и предлагаемые решения могут не соответствовать моему вопросу.

Я делюсь кодом ниже.Пожалуйста, поделитесь своими мыслями.

BrandServiceImpl.java

package com.thewatchcompany.modelsdb.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.thewatchcompany.modelsdb.domain.core.Brand;
import com.thewatchcompany.modelsdb.repository.BrandRepository;

@Service("brandService")
public class BrandServiceImpl extends AbstractResourceService<Brand, 
BrandRepository> implements BrandService {

private static final Logger LOGGER = 
LoggerFactory.getLogger(BrandServiceImpl.class);

   @Autowired
   public BrandServiceImpl(BrandRepository brandRepository) {
       super(brandRepository);
       LOGGER.info(" brandRepository : {} ", brandRepository);
   }

   protected Class<Brand> getResourceType() {
       return Brand.class;
   }
}

AbstractResourceService.java

Обратите внимание, что тестовый пример не выполняется в этом файле, где мы устанавливаемСоздатель использует setCreator () и вызывает статический метод getRequestor () из служебного класса ModelsDBUtil.java

package com.thewatchcompany.modelsdb.service;

import static com.thewatchcompany.modelsdb.ModelsDbUtil.getRequestor;

import java.util.List;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.repository.MongoRepository;

import com.thewatchcompany.modelsdb.domain.SearchRequest;
import com.thewatchcompany.modelsdb.domain.core.AbstractResource;
import com.thewatchcompany.modelsdb.domain.core.Resource;
import com.thewatchcompany.modelsdb.exception.ResourceNotFoundException;
import com.thewatchcompany.modelsdb.repository.MongoCustomRepository;

public abstract class AbstractResourceService<T extends Resource, R extends 
MongoRepository<T, String> & MongoCustomRepository<T>>
        implements ResourceService<T> {

    private static final Logger LOGGER = 
    LoggerFactory.getLogger(AbstractResourceService.class);

    private final R repository;

    public AbstractResourceService(R newRepository) {
        this.repository = newRepository;
    }

    protected abstract Class<T> getResourceType();

    protected void validateAdd(T resource) {

    }   

    /** {@inheritDoc} */   
    public T add(T resource) {

        LOGGER.info("Adding resource : {}", resource.getClass().getSimpleName());

        validateAdd(resource);

        if (resource instanceof AbstractResource) {
        ((AbstractResource) resource).setCreationInstant(System.currentTimeMillis()).setCreator(getRequestor());
        } else {
            LOGGER.warn("Invalid resource type: {}", resource.getClass().getName());
        }

        return repository.save(resource);
    }
}

ModelsDbUtil.java

package com.thewatchcompany.modelsdb;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import com.thewatchcompany.modelsdb.domain.core.Resource;
import com.thewatchcompany.modelsdb.exception.ResourceNotFoundException;
import com.thewatchcompany.modelsdb.service.ResourceService;

public final class ModelsDbUtil {

    private ModelsDbUtil() {
        // Prohibit instantiation
    }

    public static String getRequestor() {
        final Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).getUsername();
        }
        return null;
    }
}

Наконец, тестовый класс:

package com.thewatchcompany.modelsdb.service;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import com.thewatchcompany.modelsdb.ModelsDbUtil;
import com.thewatchcompany.modelsdb.domain.core.Brand;
import com.thewatchcompany.modelsdb.repository.BrandRepository;
import mockit.MockUp;

// @RunWith(PowerMockRunner.class)
// @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
// @PrepareForTest(ModelsDbUtil.class)
// @RunWith(JMockit.class)
@RunWith(SpringRunner.class)
@SpringBootTest
public class BrandServiceTest {

    @MockBean
    private BrandRepository brandRepository;

    @Autowired
    private BrandService brandService;

    private Brand brand;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

        brand = new Brand();
        brand.setId("001");
        brand.setName("Panerai");
        brand.setDescription("Panerai watches");
        brand.setActive(true);
    }

    @Test
    public void testAdd() {

        when(brandRepository.save(ArgumentMatchers.any(Brand.class)))
             .thenReturn(brand);

        // final ModelsDbUtil handler2 = spy(ModelsDbUtil.class);
        // doReturn("").when(handler2).getRequestor();

       // doReturn("").when(modelsDBUtil.getRequestor());
       // when(ModelsDbUtil.getRequestor()).thenReturn("");

       // final AbstractResource handler = spy(AbstractResource.class);
       // Mockito.ignoreStubs(handler.setCreator(ArgumentMatchers.anyString()));        

        // new MockUp<ModelsDbUtil>() {
        //            @mockit.Mock
        //            String getRequestor() {
        //                return "dssd";
        //            }
        //        };

        //final String user = Deencapsulation.invoke(ModelsDbUtil.class, "getRequestor"); //Null-pointer exception
        //assertEquals("user", user); 

        final Brand savedBrand = brandService.add(brand);
        assertEquals(savedBrand, brand);
    }
}
...