在进行单元测试时,不希望您使用数据库进行测试,或者至少不要对尚未准备进行单元测试的数据库进行测试。使用数据库进行测试,并因此同时测试应用程序的不同层通常被视为集成测试。使用单元测试时,您应该仅测试方法的作用,根据不同参数返回的结果以及何时(或不应该)失败。
非常期望在您的方法中可以从其他类调用X方法。您没有测试这些X方法,因此您需要模拟这些方法。
我想您正在用Java编写代码,在这种情况下,您将拥有诸如Mockito之类的出色模拟框架,这可能会对您有所帮助。无论您是否使用模拟框架都是您的选择,我只是说它们会为您节省很多时间,至少我提到的框架并不复杂。
如果您只想编写自己的模拟程序进行实验,那么假设您具有以下CustomerRepository
类:
public class CustomerRepository {
public CustomerDTO getCustomer(int id) {
...
}
}
您可以CustomerRepository
通过以下方式编写自己的模拟类和肮脏类:
public class MockedCustomerRepository extends CustomerRepository {
public boolean bThrowDatabaseException;
public boolean bReturnNull;
public boolean bReturnCustomerWrongId;
public boolean bReturnCustomerWithId;
public CustomerDTO getCustomer(int id) {
if(bThrowDatabaseException) {
throw new DatabaseException("xxx");
} else if(bReturnNull) {
return null;
} else if(bReturnCustomerWrongId) {
throw new CustomerNotExistException(id);
} else if(bReturnCustomerWithId) {
return new CustomerDTO(id);
}
}
}
然后,在测试用例中,基本上将您的“标准”实例替换CustomerRepository
为模拟实例,该实例将允许您测试方法的各种结果getCustomer
:
public class CustomerRestTest {
public void testGetCustomer_databaseFailure() {
MockedCustomerRepository dto = new MockedCustomerRepository();
dto.bThrowDataBaseException = true;
yRestClass rest = new MyRestClass();
rest.dto = dto;
rest.getCustomer(0);
// depending on what you do in your getCustomer method, you should check if you catched the exception, or let it pass, etc.. Make your assertions here
public void testGetCustomer_customerNotExist() {
// etc.
}
}
通常,每种测试方法都只能测试一件事,这有助于使测试范围缩小,并专注于一项任务。
我将重复一遍:-)编写一个完整的模拟类需要花费一些时间。考虑使用模拟框架,编写代码的人越少,产生的错误就越少,对吗?模拟抛出异常或为给定参数返回给定值的方法简直是小菜一碟,需要2或3行(至少包含嘲笑)
希望这有助于测试您的REST方法。