测试从单元返回的对象的所有可能条件或状态是否正确?
想象一下对以下示例场景进行单元测试。假设我已经模拟了 CustomerDAO 以返回有效的客户和客户订单。测试这个场景相当容易。除非我开始测试布尔值以确定客户是否有订单。在某些现实场景中,他们不会有订单。那么我是否需要在我的模拟 DAO 中添加一些条件来返回没有订单的客户,然后也进行测试?现在想象一下它要复杂得多,并且 DTO 的多个部分可能包含各种信息,具体取决于从数据库返回的实际结果。我需要测试所有这些不同的条件吗?
public class Manager {
public CustomerDTO getCustomerInformation() {
CustomerDAO customerDAO = new CustomerDAO();
CustomerDTO customerDTO = new CustomerDTO();
customerDTO.setCustomer(customerDAO.getCustomer(1));
customerDTO.setCustomerOrders(customerDAO.getCustomerOrders(1));
if (!customerDTO.getCustomerOrders.isEmpty()) {
customerDTO.setHasCustomerOrders(true);
}
return customerDTO;
}
}
Imagine unit testing the following sample scenario. Let's say I've mocked out the CustomerDAO in order to return a valid customer and customer orders. Testing this scenario is fairly easy. Except when I get to testing the boolean for whether or not a customer has orders. In some real world scenarios they will not have orders. So do I need to add some condition in my mock DAO that will return a customer with no orders, and then test that as well? Now imagine it is much more complicated and there are several pieces of the DTO that could contain various bits of information depending on the real results coming back from the database. Do I need to test all of those various conditions?
public class Manager {
public CustomerDTO getCustomerInformation() {
CustomerDAO customerDAO = new CustomerDAO();
CustomerDTO customerDTO = new CustomerDTO();
customerDTO.setCustomer(customerDAO.getCustomer(1));
customerDTO.setCustomerOrders(customerDAO.getCustomerOrders(1));
if (!customerDTO.getCustomerOrders.isEmpty()) {
customerDTO.setHasCustomerOrders(true);
}
return customerDTO;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
简而言之,我认为是的,您应该测试当 DAO 返回各种内容时,DTO 上是否存在预期状态。否则,您如何确信 DTO 将准确表示数据存储中的数据?
您应该使用测试所需的数据为每个测试创建一个模拟 DAO,或者为每个需要测试的状态创建一个模拟 DAO。
我可能有这样的测试:
CustomerHasOrders_WhenDaoReturnsNoOrders_ReturnsFalse
CustomerHasOrders_WhenDaoReturnsOrders_ReturnsTrue
GetCustomer_WhenDaoReturnsCustomer_CustomerIsSame
GetCustomerOrders_WhenDaoReturnsOrders_OrdersAreTheSame
GetCustomerOrders_WhenDaoReturnsNoOrders_OrdersAreEmpty
然后测试如果对 Dao 的任何调用失败会发生什么...
在这个示例中,该标志在 DTO 中似乎是多余的,因为它只是其他数据的不同表示。您可以将其实现为 CustomerDTO 上的扩展方法,或者 setCustomerOrders 中的某些逻辑。如果要通过线路发送 DTO,并且该功能不一定存在,那么您可以排除该属性,客户端只需检查是否有任何订单,方式与您的 customerDTO 相同.getCustomerOrders.isEmpty()
In short, I think yes you should test that when the DAO returns various things that the expected state exists on the DTO. Otherwise how can you have an confidence that the DTO will be an accurate representation of the data that was in the datastore?
You should create either a mock DAO per test with the required data for the test, or a mock DAO for each state that needs to be tested.
I'd probably have tests like:
CustomerHasOrders_WhenDaoReturnsNoOrders_ReturnsFalse
CustomerHasOrders_WhenDaoReturnsOrders_ReturnsTrue
GetCustomer_WhenDaoReturnsCustomer_CustomerIsSame
GetCustomerOrders_WhenDaoReturnsOrders_OrdersAreTheSame
GetCustomerOrders_WhenDaoReturnsNoOrders_OrdersAreEmpty
and then tests for what happens if any of the calls to the Dao fail...
In this example it seems that the flag is redundant in the DTO, as it is just different representations of other data. You could implement that as an extension method on CustomerDTO, or some logic in the setCustomerOrders. If the DTO is to be sent over the wire and the functionality won't neccessarily be there then you could exclude the property and the client could just do the check to see if there are any orders in the same way you are
customerDTO.getCustomerOrders.isEmpty()
您想要测试 Manager 是否正在将 Customer 及其相关数据转换为 CustomerDTO。所以是的,你必须测试所有这些不同的场景。但不要在一次测试中完成所有操作。每个测试都应该以成功或失败结束。我的意思是:
因为这样,当有 1 个错误和 4 个错误时,就有一项测试失败。您修复了一个错误并期望测试能够通过,但随后在下一行再次失败。将所有断言放入不同的测试中并使用描述名称。
You want to test if Manager is converting Customer and it's related data to CustomerDTO. So yes you have to test all those different scenarios. But don't do it all in one test. Each test should reach it's end either finishing with success or failure. What I mean:
Because then you have one test failing when there is one error and when there are 4 errors. You fix one bug and expect test to pass but then it fails again on next line. Put that all asserts in different tests with describing names.