[英]Is it good way to unit test this method?
我需要使用Junit / Mockito测试此方法。 实际上,我无法使用Mockito正确编写测试,因此我使用了自己的输入来代替模拟扫描仪。 我不知道我是否做对了。 (有人知道如何使用Mockito吗?)
这是我要测试的方法:
public RentingACar rentACar(Scanner input) {
RentingACar rentingACar = new RentingACar();
System.out.print("Brand: ");
rentingACar.setBrand(input.next());
System.out.print("Name: ");
rentingACar.setName(input.next());
System.out.print("Surname: ");
rentingACar.setSurname(input.next());
System.out.print("Rent Date: ");
rentingACar.setRentDate(input.next());
System.out.print("Client number: ");
rentingACar.setClientNumber(input.nextInt());
return rentingACar;
}
这是我的测试:
@Test
void rentACar() {
Scanner scanner = new Scanner("Mazda\nPeter\nParker\n20.02\n1234");
ClientDataGetter clientDataGetter = new ClientDataGetter();
RentingACar rentingACar = clientDataGetter.rentACar(scanner);
assertNotNull(rentingACar);
assertEquals("Mazda", rentingACar.getBrand());
assertEquals("Peter", rentingACar.getName());
assertEquals("Parker", rentingACar.getSurname());
assertEquals("20.02", rentingACar.getRentDate());
assertEquals(1234, rentingACar.getClientNumber());
}
有什么意义吗?
为什么在不需要Mockito时会使用Mockito,地狱,使用Mockito编写代码比没有Mockito的问题更多? Mockito是完全不得已的选择(例如,模拟数据库或外部服务),即使这样,是否应该使用它还是值得怀疑的(而不是仅仅编写自己的FakeDatabase
或FakeExternalService
)。 这里绝对不需要,一个被嘲笑的Scanner
还能提供什么帮助?
我说您的方法很好,即使您要测试的代码仍有很多不足之处。 因为这个问题是关于测试的,所以我不会谈论代码本身。
您仅测试了所谓的“快乐路径”,这意味着输出完美且一切正常的情况。
您还需要做的是测试边缘情况(输入最大/最小时,例如L.MIN_VALUE / 0 / Long.MAX_VALUE的数字,字符串的长度为0等),例如使用空/一个字母名称,客户编号以0开头。
毕竟,您需要测试输入是否完全错误:没有\\n
符号,没有日期应为日期的等等,这里有很多可能性。 您可能会发现代码还不够,您将不得不对其进行更改(也许添加一些输入验证)。 这就是为什么最好从测试(测试驱动的开发)开始的原因,您可以在编写代码之前先看到必须做的验证,然后您将为此做好准备。 这是简单的情况,但是向已经存在的代码中添加重要的功能并不总是那么容易,而且如果某人已经使用了该代码,甚至可能会有风险。 我见过很多情况,当某人需要进行这样的修改时,但是如果没有巨大的重构是不可能的,所以这就是他们所做的(请不要做):
if(mySpecialCase) {
// all the logic
} else {
// all the logic, almost identical to the logic above
}
编辑:回复您的评论- Why is it bad practice to make if conditions?
我不仅在这里讨论if
条件。 我说的是两个潜在的重复代码if
分支,他们将最有可能有非常相似的代码。 想象一下,你有其他的变化使,你得再添if
这两个分支,它成为一个烂摊子。
If
条件也不应该被过度使用,尤其是当条件归结为许多不同的分支时。 仅通过查看代码就很难调试,测试和查看正在发生的事情。 一定要有人(或您)通过查看并分析代码来了解代码的作用,这一点非常重要。 解决这个问题通常并不容易,需要使用一些设计模式 (例如decorator) ,有时甚至是一个简单的开关也可以提供很多帮助。
这就是我使用Mockito编写测试的方式。
import org.junit.Test;
import java.util.Scanner;
import static org.mockito.Mockito.*;
public class ClientDataGetterTest {
ClientDataGetter clientDataGetter = new ClientDataGetter();
@Test
public void testRentACar() {
// define input data (test Scanner object)
Scanner scanner = new Scanner("Mazda\nPeter\nParker\n20.02\n1234");
// call you method
RentingACar rentACar = spy(new RentingACar());
clientDataGetter.rentACar(rentACar, scanner);
// Verify that the methods were called with exact parameter values and exactly one time each
verify(rentACar, times(1)).setBrand("Mazda");
verify(rentACar, times(1)).setName("Peter");
verify(rentACar, times(1)).setSurname("Parker");
verify(rentACar, times(1)).setRentDate("20.02");
verify(rentACar, times(1)).setClientNumber(1234);
// Old code
/*
//check the results
assertEquals("Mazda", rentingACar.getBrand());
assertEquals("Peter", rentingACar.getName());
assertEquals("Parker", rentingACar.getSurname());
assertEquals("20.02", rentingACar.getRentDate());
assertEquals(1234, rentingACar.getClientNumber());
*/
}
Mockito正在确保您的二传手被叫到。
我个人认为,如果您的RentingACar看起来像一个简单的POJO,那么就不需要像我一样模拟它了,那么您的方法很好。
您可以通过如下定义Mockito for Scanner://为扫描器定义模拟
Scanner scanner = mock(Scanner.class);
when(scanner.next()).thenReturn("Mazda","Peter","Parker","20.02","1234");
但是嘲笑不能嘲笑最后的课程。 标准的java.util.Scanner是最终类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.