带有Mockito的单元测试Spring MVC控制器 [英] Unit testing spring mvc controller with mockito
问题描述
我正在使用Mockito和Junit并针对Spring MVC运行单元测试 我的代码流是:
i'm using mockito and junit and run unit test against spring mvc my flow of code is:
Service Layer
-> Model Layer
-> Controller Layer
我成功使用以下代码针对模型层对Controller进行了测试:
i was successfully testing the Controller against the model layer with the code:
@RunWith(MockitoJUnitRunner.class)
public class HashLinkerControllerTest {
private static final Logger LOGGER = Logger
.getLogger(HashLinkerControllerTest.class);
@Mock
private HashLinkerModel modelMock;
@InjectMocks
private HashLinkerController controller;
private MockMvc mockMvc;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void update() throws Exception {
int date = 123;
String hashToCheck = "asdfasdfasdfasdfas";
HashLinker first = this.createHashLinker(hashToCheck, "some name",
"some des", "some data", date);
when(modelMock.update(first)).then(returnsFirstArg());
mockMvc.perform(
put("/api/hashService/" + hashToCheck)
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(
TestUtil.convertObjectToJsonBytesWithSettersOnly(first))
.accept(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(
content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.hash", is(hashToCheck)))
.andExpect(jsonPath("$.description", is("some des")))
.andExpect(jsonPath("$.name", is("some name")));
verify(modelMock, times(1)).update(first);
verifyNoMoreInteractions(modelMock);
}
但是现在我正在寻找一种测试3层结构的方法.即针对控制器测试服务.我想出了:
but now i'm looking for a way to test the 3 layers structure. i.e testing the service against the controller . i came up with :
@RunWith(MockitoJUnitRunner.class)
public class HashLinkerControllerServiceLayerTest {
private static final Logger LOGGER = Logger
.getLogger(HashLinkerControllerServiceLayerTest.class);
@Mock
private HashLinkerService serviceMock;
@InjectMocks
// @Mock
private HashLinkerModel modelMock;
private HashLinkerController controller;
private MockMvc mockMvc;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
controller = new HashLinkerController(modelMock);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
并使用
@Test
public void update() throws Exception {
int date = 123;
String hashToCheck = "asdfasdfasdfasdfas";
HashLinker first = this.createHashLinker(hashToCheck, "some name",
"some des", "some data", date);
when(serviceMock.update(first)).then(returnsFirstArg());
mockMvc.perform(
put("/api/hashService/" + hashToCheck)
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(
TestUtil.convertObjectToJsonBytesWithSettersOnly(first))
.accept(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(
content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.hash", is(hashToCheck)))
.andExpect(jsonPath("$.description", is("some des")))
.andExpect(jsonPath("$.name", is("some name")));
verify(serviceMock, times(1)).update(first);
verifyNoMoreInteractions(serviceMock);
}
测试与以上相同,但我将modelMock
更改为serviceMock
.由于某种原因该测试失败.我得到404.
有什么想法吗?
the test is the same as above expect i have changed modelMock
to be serviceMock
. for some reason this test fails . i get 404.
any ideas?
version:
<spring.core.version>3.2.6.RELEASE</spring.core.version>
<spring.test.version>3.2.6.RELEASE</spring.test.version>
<mockito.version>1.9.5</mockito.version>
<junit.version>4.8.2</junit.version>
编辑:
@Component
public class HashLinkerModel {
private static final Logger LOGGER = Logger.getLogger(HashLinkerModel.class);
HashLinkerService service;
/** The unicode service. */
UnicodeService unicodeService;
@Autowired
public HashLinkerModel(HashLinkerService service, UnicodeService unicodeService){
this.service = service;
this.unicodeService = unicodeService;
}
/**
* check if hash exists before creation
* @param toHash
* @return
*/
private HashLinker checkAndcreate(HashLinker toHash){
String hash = this.createHash(toHash.getData());
toHash.setHash(hash);
LOGGER.info("add " + hash + ". this is the hash of string " + toHash.getData());
/* if this hash already in system. return null. otherwise create */
HashLinker exists = service.findByHash(toHash.getHash());
if (null != exists)
return exists;
//** we use service here **
return service.create(toHash);
}
public HashLinker create(HashLinker entity) {
// TODO Auto-generated method stub
RestPreconditions.checkRequestElementNotNull(entity, LOGGER);
RestPreconditions.checkRequestElementNotNull(entity.getData(), LOGGER);
String uniName = getUniHelper().unicode(entity.getName());
String uniDesc = getUniHelper().unicode(entity.getDescription());
HashLinker toHash = new HashLinker();
toHash.setData(entity.getData());
toHash.setType(entity.getType());
String baseURL = entity.getBaseURL();
if (null != baseURL)
baseURL = (baseURL.length() > HashLinker.getIntMaxBaseURL()) ? baseURL.substring(0, HashLinker.getIntMaxBaseURL()) : baseURL;
toHash.setBaseURL(baseURL);
toHash.setStatus(0);
// update lecker's macros results
toHash.setName(uniName);
toHash.setDescription(uniDesc);
return checkAndcreate(toHash);
}
推荐答案
放行
verify(serviceMock, times(1)).update(first);
之后
mockMvc.perform(
put("/api/hashService/" + hashToCheck)
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(
TestUtil.convertObjectToJsonBytesWithSettersOnly(first))
.accept(TestUtil.APPLICATION_JSON_UTF8));
但在模拟Mvc断言之前,以验证是否使用了您的模拟.
but before mockMvc assertions, to verify that your mock is used.
您的代码的一般问题:
-
使用注释
@RunWith(MockitoJUnitRunner.class)
无需手动初始化Mockito.
With annotation
@RunWith(MockitoJUnitRunner.class)
initializing Mockito manually is not necessary.
@MockitoJUnitRunner
初始化带有Mock注释的模拟,因此不需要显式使用 MockitoAnnotations.initMocks(Object).
Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary.
单元测试
Unit testing
我正在寻找一种测试三层结构的方法.
i'm looking for a way to test the 3 layers structure.
当测试涉及三层时,该测试是集成测试.
When three layers are involved in the test, the test is an integration test.
在单元测试中,最好有许多小的方法来测试不同的行为.因此,一种方法应该测试HTTP响应,第二种方法应该验证是否调用了服务.
In unit testing it is better to have many small method for testing different behaviour. So one method should test HTTP Response, second should verify if service is invoked.
这篇关于带有Mockito的单元测试Spring MVC控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!