我正在尝试使用Mockito添加测试用例。但是在此方法内部,有一个对静态方法的调用,该方法根据逻辑返回null,因为它是静态方法,所以我无法模拟它的行为。我需要模拟它或以某种方式绕过它。
我在堆栈溢出中经历了类似的链接,但是无法解决我的问题,可能是因为几年前有人提出了一些疑问,建议的解决方案可能不适合我的问题。
我正在分享下面的代码。请分享您的想法。
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()设置Creator,并从名为ModelsDBUtil.java的实用工具类中调用静态方法getRequestor()。
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);
}
}