Java 春季及;Mockito:在单元测试中调用实际对象
这是我要测试的课程Java 春季及;Mockito:在单元测试中调用实际对象,java,spring,unit-testing,junit,mockito,Java,Spring,Unit Testing,Junit,Mockito,这是我要测试的课程 public class AuthErrorResponseWriter { @Autowired TransResponse svcResponse; @Override public void writeResponse(HttpServletResponse response) { //Set the Http status respons
public class AuthErrorResponseWriter {
@Autowired
TransResponse svcResponse;
@Override
public void writeResponse(HttpServletResponse response) {
//Set the Http status
response.setStatus(HttpStatus.FORBIDDEN.value());
svcResponse.setMessage(Constants.AUTHENTICATION_ERROR);
svcResponse.setStatus(HttpStatus.FORBIDDEN.toString());
ObjectMapper mapper = new ObjectMapper();
//Write the response
try {
Writer writer = response.getWriter();
writer.write(mapper.writeValueAsString(svcResponse));
writer.flush();
writer.close();
} catch (IOException ioex) {
logger.error("Problem producing authentication error http response",ioex);
}
}
}
下面是我编写的单元测试代码
RunWith(SpringRunner.class)
@WebMvcTest({AuthErrorResponseWriter .class})
@ComponentScan("com.demo.service")
public class AuthErrorResponseWriterTest {
@Mock
HttpServletResponse responseMock;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testResponse(){
TransResponse mockResponse = new TransResponse();
mockResponse.setMessage(Constants.AUTHENTICATION_ERROR);
mockResponse.setStatus(HttpStatus.FORBIDDEN.toString());
AuthErrorResponseWriter authErrorWriter = new AuthErrorResponseWriter ();
PrintWriter writerMock = mock(PrintWriter.class);
try {
when(responseMock.getWriter()).thenReturn(writerMock);
} catch (IOException ioex) {
//assertTrue(false);
}
authErrorWriter.writeResponse(responseMock);
verify(responseMock).setStatus(HttpStatus.FORBIDDEN.value());
}
}
当我执行这个Junit时,我得到一个空指针异常
svcsresponse.setMessage(常量.身份验证错误)
svcResponse为null,尽管我已经对它进行了模拟
请有人告诉我,为什么它不拿起模拟对象,并寻找实际的
还有,如果我写Junit是一种合适的方式
svcResponse为null,尽管我已经对它进行了模拟
不,你没有嘲笑它。这就是您在代码中所做的:
TransResponse mockResponse = new TransResponse();
mockResponse.setMessage(Constants.AUTHENTICATION_ERROR);
mockResponse.setStatus(HttpStatus.FORBIDDEN.toString());
你应该这样做:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
您必须在目标类中注入模拟,如下所示:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
并使用,authErrorWriter
,而不是在测试中创建该类的新实例
然后你可以这样做:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
svcResponse为null,尽管我已经对它进行了模拟
不,你没有嘲笑它。这就是您在代码中所做的:
TransResponse mockResponse = new TransResponse();
mockResponse.setMessage(Constants.AUTHENTICATION_ERROR);
mockResponse.setStatus(HttpStatus.FORBIDDEN.toString());
你应该这样做:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
您必须在目标类中注入模拟,如下所示:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
并使用,authErrorWriter
,而不是在测试中创建该类的新实例
然后你可以这样做:
@Mock
private TransResponse mockResponse;
@InjectMocks
private AuthErrorResponseWriter authErrorWriter;
Mockito.doNothing().when(mockResponse).setMessage(Constants.AUTHENTICATION_ERROR);
您可能希望使用Mockito的runner而不是Spring(据我所见,您根本不需要Spring的上下文):
您可能希望使用Mockito的runner而不是Spring(据我所见,您根本不需要Spring的上下文):
WebMvcTest
用于测试Spring MVC组件。AuthErrorResponseWriter
是控制器吗?然后,我看到您自己实例化了AuthErrorResponseWriter
,所以什么都不做。然后,您根本不模拟svcsresponse
,因此它是空的。使用WebMvcTest
时,不会加载实际上下文(仅加载测试的SpringMVC控制器的最小值。组件不是自动连接的,您需要模拟它们。您应该避免字段注入,并将其替换为构造函数注入。这使测试代码更容易。此外,您真的需要在测试中使用Spring吗?如果不需要,请手动将依赖项注入类中以进行测试。)通过MockitosWhitebox.setInternalState(…)
或SpringsReflectionUtils.setField(…)
方法进行测试(如果没有可用的构造函数注入)这是spring boot应用程序的一部分,所以我添加了WebMvcTest。现在在解释之后我删除了它。谢谢!WebMvcTest
用于测试spring MVC组件。是不是AuthErrorResponseWriter
控制器?然后,我看到你自己实例化了AuthErrorResponseWriter
,所以什么都不做。然后,你就没有moc了ksvcsresponse
,因此它是空的。当使用WebMvcTest
时,不会加载真正的上下文(仅加载测试的SpringMVC控制器的最小值。组件不是自动连接的,您需要模拟它们。您应该避免字段注入,并将其替换为构造函数注入。这使测试代码更容易。此外,您真的需要在测试中使用Spring吗?如果不需要,请手动将依赖项注入类中以进行测试。)通过MockitosWhitebox.setInternalState(…)
或SpringsReflectionUtils.setField(…)
方法进行测试(如果没有可用的构造函数注入),这是spring boot应用程序的一部分,所以我添加了WebMvcTest。现在在解释之后,我已经删除了它。谢谢!因为它部分正确),您需要将您的mock注入目标类,以便spring在自动连接过程中使用您的mock。@RyanS您完全正确。我正在将该部分添加到我的答案中。更好的是,不要使用@InjectMocks
,避免这种混乱。通过构造函数注入依赖项。请演示@ChristopherSchneiderI真的看不到不使用构造函数注入的任何理由。构造函数可能很大,但这更多的是暗示您的类太大。下面是一个很好的答案,它是一个构造函数注入的示例,并在单元测试时使用它。利用它(因为它部分正确),您需要将您的mock注入目标类,以便spring在自动连接过程中使用您的mock。@RyanS您完全正确。我正在将该部分添加到我的答案中。更好的是,不要使用@InjectMocks
,避免这种混乱。通过构造函数注入依赖项。请演示@ChristopherSchneiderI真的看不到任何不使用构造函数注入的理由。构造函数可能很大,但这更多的是暗示您的类太大。下面是一个很好的答案,它是一个构造函数注入示例,并在单元测试时使用它。