【发布时间】:2014-02-26 15:13:38
【问题描述】:
我已经构建了使用 MongoDB 的应用程序,但在测试时遇到了问题。
只要我使用 JPA 和一些关系数据库,我就使用了一些测试层,将持久性切换到内存数据库(linke HSQLDB 或 MySQL)用于测试目的。通过这种方式,我能够限制 IO 操作并加快测试速度。 但是对于 MongoDB 和 Spring Data,使用基于扩展 MongoRepository 的接口的存储库非常方便。
我的问题是在使用存储库时如何处理单元测试和功能测试?例如,我有一个简单的类,它被注释为 mongo 文档:
public class Company {
@Id
private String id;
@NotEmpty
private String name;
private String description;
private String website;
private String logo;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
及相关仓库:
@Repository
public interface CompanyRepository extends MongoRepository<Company, Serializable> {
}
在对应的控制器中使用:
@RestController
public class CompanyController {
private static final Logger log = LoggerFactory.getLogger(CompanyController.class);
@Autowired
private CompanyRepository repository;
@RequestMapping(value = "/company", method = RequestMethod.POST)
public void create(@Valid @RequestBody(required = true) Company company) {
repository.save(company);
}
}
最后我做了两个测试(但它可能同时涵盖两个任务),涵盖控制器 api 和数据格式(我在其中模拟存储库以防止 IO 操作,并且效果很好),第二个我想确保传递的对象已成功持久化。当它出现时,它并不那么简单。首先(如果我错了,请纠正我)没有内存中的 mongo 实现。其次,由于我想是继承,我无法通过模拟执行 save 方法进行验证。
@ContextConfiguration(classes = Application.class)
@WebAppConfiguration
public class CompanyControllerNGTest extends AbstractTestNGSpringContextTests {
@Mock
private CompanyRepository repositoryMock;
@Autowired
@InjectMocks
private CompanyController controller;
private MockMvc mockMvc;
@BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@DataProvider
public static Object[][] companyJsonProvider() {
return new Object[][]{
{Json.createObjectBuilder()
.add("name", "JakasFirma")
.add("description", "jakas firma opis")
.add("website", "www.jakasfirma.com")
.add("logo", "jakies logo")
.build(), status().isOk()},
{Json.createObjectBuilder()
.add("name", "JakasFirma")
.build(), status().isOk()},
{Json.createObjectBuilder()
.add("description", "jakas firma opis")
.add("website", "www.jakasfirma.com")
.add("logo", "jakies logo")
.build(), status().isBadRequest()},
{Json.createObjectBuilder()
.build(), status().isBadRequest()},
};
}
@Test(dataProvider = "companyJsonProvider", enabled = false)
public void apiTest(JsonObject companyJson, ResultMatcher expectedStatus) throws Exception {
//given
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
String content = companyJson.toString();
//when
mockMvc.perform(post("/company").contentType(MediaType.APPLICATION_JSON).content(content)).
//then
andExpect(expectedStatus);
}
@Test
public void shouldCreate() throws Exception {
//given
//when
controller.create(mock(Company.class));
//then
//verify(repositoryMock, times(1)).save(any(Iterable.class));
}
}
我考虑在控制器和存储库之间引入一个 dao 层,可以模拟和验证机器人,它增加了更多复杂性和强制封装存储库使用的每个方法。它也不能解决问题,而是将其部分移至较低级别。 有什么方法或做法可以帮助解决这类问题吗?或者也许我应该对 mongo 使用不同的方法?
【问题讨论】:
标签: java spring mongodb unit-testing spring-data-mongodb