- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为我的单元测试项目(Spring boot rest controller)创建基础,我在传递@InjectMocks 值时遇到问题,因为它仅在@Before 中评估,因此当我尝试访问它时会抛出空指针外面
请提供一些解决问题的技巧?
非常感谢
Ps:关于最佳实践的任何其他建议或我在单元测试中对我当前的基类测试做错的事情也将不胜感激
要测试的类(休息 Controller )
@RestController
@RequestMapping("/management")
@Api(description = "Users count connections", produces = "application/json", tags = {"ConnectionManagement API"})
public class ConnectionManagementControllerImpl implements ConnectionManagementController {
@Autowired
private ConnectionManagementBusinessService connectionManagementBusinessService;
@Override
@PostMapping(value = "/countConnectionsByInterval" , consumes = MediaType.TEXT_PLAIN_VALUE , produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ApiOperation(value = "count all users connections by interval")
public ResponseEntity<List<ConnectionsCountDto>> countConnectionsByInterval(@RequestBody String format) {
List<ConnectionsCountDto> connectionManagement = connectionManagementBusinessService.countConnectionsByInterval(format);
return new ResponseEntity<List<ConnectionsCountDto>>(connectionManagement, HttpStatus.OK);
}
抽象基础测试
public abstract class AbstractBaseTest<C> {
public MockMvc mockMvc;
private Class<C> clazz;
private Object inject;
protected abstract String getURL();
protected final void setTestClass(final Class<C> classToSet, final Object injectToSet) {
clazz = Preconditions.checkNotNull(classToSet);
inject = Preconditions.checkNotNull(injectToSet);
}
@Before
public void init() throws Exception {
MockitoAnnotations.initMocks(clazz);
mockMvc = MockMvcBuilders.standaloneSetup(inject).build();
}
protected MockHttpServletResponse getResponse(MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
get(getURL()).
accept(produces)).
andReturn().
getResponse();
return response;
}
protected MockHttpServletResponse postResponse(String content , MediaType consumes , MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
post(getURL()).
content(content).
contentType(consumes).
accept(produces)).
andReturn().
getResponse();
return response;
}
}
测试类
@RunWith(MockitoJUnitRunner.class)
public class ConnectionManagementControllerImplTest extends AbstractBaseTest<ConnectionManagementControllerImpl>{
@Mock
private ConnectionManagementBusinessService connectionManagementBusinessServiceMocked;
@InjectMocks
private ConnectionManagementControllerImpl connectionManagementControllerMocked;
public ConnectionManagementControllerImplTest() {
super();
setTestClass(ConnectionManagementControllerImpl.class , connectionManagementControllerMocked); // null pointer there
}
@Test
public void countConnectionsByInterval() throws Exception {
// given
given(connectionManagementBusinessServiceMocked.countConnectionsByInterval(Mockito.anyString()))
.willReturn(new ArrayList<ConnectionsCountDto>());
// when
MockHttpServletResponse response = postResponse("day" , MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON_UTF8);
// then
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
}
@Override
protected String getURL() {
return "/management/countConnectionsByInterval";
}
最佳答案
这按预期工作。但是,您可以手动设置模拟并将它们注入(inject) ConnectionManagementControllerImplTest
构造函数(在调用 setTestClass(...)
之前):
public ConnectionManagementControllerImplTest() {
super();
connectionManagementBusinessServiceMocked = Mockito.mock(ConnectionManagementBusinessService.class);
connectionManagementControllerMocked = new ConnectionManagementControllerImpl();
connectionManagementControllerMocked.setConnectionManagementBusinessService(connectionManagementBusinessServiceMocked);
setTestClass(ConnectionManagementControllerImpl.class, connectionManagementControllerMocked);
}
不要忘记删除 @Mock
和 @InjectMocks
注释。顺便说一句,在这种情况下,您甚至可以删除 @RunWith(MockitoJUnitRunner.class)
。
更新: 测试类的构造函数和用 @Before
注释的“init”方法都会为每个测试执行。不同之处在于 Mockito 注释是在构造函数和 @Before
方法调用之间处理的。
因此您可以稍微更改您的代码以获得积极的结果:
ConnectionManagementControllerImplTest
中创建“init”方法(使用 @Before
注释)并将 setTestClass()
从构造函数中移入其中(在那个特殊情况下,您还可以删除整个构造函数,因为它只包含 super()
调用)。setTestClass()
行之后添加 super.init()
(否则 JUnit 将忽略父类中的“init”方法)。@Before
注释。以这种方式重构的代码示例:
public abstract class AbstractBaseTest<C> {
public MockMvc mockMvc;
private Class<C> clazz;
private Object inject;
protected abstract String getURL();
protected final void setTestClass(final Class<C> classToSet, final Object injectToSet) {
clazz = Preconditions.checkNotNull(classToSet);
inject = Preconditions.checkNotNull(injectToSet);
}
@Before //this annotation can be removed
public void init() throws Exception {
MockitoAnnotations.initMocks(clazz); //this line also can be removed because MockitoJUnitRunner does it for you
mockMvc = MockMvcBuilders.standaloneSetup(inject).build();
}
protected MockHttpServletResponse getResponse(MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
get(getURL()).
accept(produces)).
andReturn().
getResponse();
return response;
}
protected MockHttpServletResponse postResponse(String content , MediaType consumes , MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
post(getURL()).
content(content).
contentType(consumes).
accept(produces)).
andReturn().
getResponse();
return response;
}
}
@RunWith(MockitoJUnitRunner.class)
public class ConnectionManagementControllerImplTest extends AbstractBaseTest<ConnectionManagementControllerImpl> {
@Mock
private ConnectionManagementBusinessService connectionManagementBusinessServiceMocked;
@InjectMocks
private ConnectionManagementControllerImpl connectionManagementControllerMocked;
//constructor can be removed
public ConnectionManagementControllerImplTest() {
super();
}
@Before
public void init() throws Exception {
setTestClass(ConnectionManagementControllerImpl.class, connectionManagementControllerMocked);
super.init();
}
@Test
public void countConnectionsByInterval() throws Exception {
// given
given(connectionManagementBusinessServiceMocked.countConnectionsByInterval(Mockito.anyString()))
.willReturn(new ArrayList<ConnectionsCountDto>());
// when
MockHttpServletResponse response = postResponse("day", MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON_UTF8);
// then
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
}
@Override
protected String getURL() {
return "/management/countConnectionsByInterval";
}
}
附言我更喜欢前一种方法,但如果您不想为 ConnectionManagementBusinessService
使用 setter,则可以选择后者。我已经测试了它们,结果是一样的。
关于java - 在@Before 之外使用@InjectMocks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55007125/
在使用 JUnit 进行单元测试时,我在传递依赖项时遇到了一些麻烦。 考虑这些代码: 这是我要测试的类的依赖注入(inject),我们称之为 Controller 。 @Inject private
我有这段代码 - @Component public class ServiceA { @Autowired private ServiceB serviceB; public
这是我要模拟的类(class)。 private MemcachedClient memcachedClient; private CachedObjectFactory cachedObjectFa
我们目前正在使用 JUnit 和 Mockito 来测试我们的代码。 我们有一个如下所示的服务接口(interface)。 public interface ServiceA { void
我已经阅读了很多关于@Mock 和@InjectMocks 的讨论,但仍然找不到使用@InjectMocks 的合适或必要的情况。事实上,我不确定当我们使用@InjectMocks 时会发生什么。 考
下面的方法等价于什么: @Mock MyType1 myType1; @Autowired @InjectMocks MyType2 myType2; 我可以将 @Mock 替换为 mock(MyTy
我有一个要测试的 RestController: import javax.validation.Valid; import org.springframework.beans.factory.ann
我创建了一个包装器,用于通过 log4j 进行日志记录,扩展 HandlerInterceptorAdapter 并保持构建类型 maven 项目。我在我的 Spring Boot 应用程序中使用这个
这是我第一次使用 Mockito 进行 junit 测试。我面临 @InjectMocks 中使用的服务的 NPE 问题。我查看了其他解决方案,但即使在遵循它们之后,它也显示相同。这是我的代码。 @R
假设我有一个类: public class Boy { @Inject @Named("birthDay"
考虑下面的代码片段: @ExtendWith(MockitoExtension.class) public class MyTest { @InjectMocks ClassA cA;
我有这样的东西 @Component public class TestController { @Autowired private TestService testService;
我正在为我的单元测试项目(Spring boot rest controller)创建基础,我在传递@InjectMocks 值时遇到问题,因为它仅在@Before 中评估,因此当我尝试访问它时会抛出
我想在一种方法中使用模拟 eventService,在另一种方法中使用真实的 eventService。 @Mock(name = "eventService") private
是的,我知道,关于 Mockito 的 @InjectMocks 已经写了很多,但是仍然有一个问题我无法解决...... 假设我们有一个有四名成员的类(class)... class A {
这到底是如何运作的?按照我的理解,不应该有。LDAPGroupAccessor 正在类中进行 new 初始化,或者可以在构造函数本身中进行 new 初始化,它没有被注入(inject),不是构造函数参
我正在 Spring Mvc 上使用 Mockito 进行 JUnit 测试。测试使用 @InjectMock 和 @Mock 以及when(method(..)).thenReturn(X)。问题是
我正在测试我的类中的两个私有(private)字段,这两个字段在构造函数中初始化。 现在,当我尝试使用带有 @InjectMocks 注释的类进行调用时,它会抛出异常: Cannot instant
我有以下类(class): public class DaoService { private Dao dao; private Map map; public DaoService
为了了解 Mockito 注释工作原理的基础知识,我浏览了一些博客。 但是我对何时手动实例化用 @InjectMocks 注释的字段存在疑问,即 @InjectMocks A a = new A();
我是一名优秀的程序员,十分优秀!