use*_*542 7 java testing unit-testing mocking mockito
所以我仍然在使用Mockito时遇到麻烦.所以我们假设我有以下类(请忽略它的逻辑或结构,它只是我从另一个类创建的一个简短示例,具有不同的名称等等.):
public class Restaurant(
@Autowired
private CustomerService customerService;
private CustomerInputData updateCustomer(CustomerInputData inputData){
String customerId = inputData.getID();
Customer customer = customerService.getCustomerById(customerID);
if(customer.getAddress() != null){
inputData.setCustomerName(customer.getCustomerName());
inputData.setCustomerCity(customer.getCustomerCity);
inputData.setCustomerLanguage(customer.getLanguage);
}
return inputData
}
}
Run Code Online (Sandbox Code Playgroud)
因此,我对单元测试的理解是,隔离所有依赖项.在这里,我将拥有客户级和客户服务.
所以要写一个测试类,我现在会做以下事情:
public class RestaurantTest()
{
@Mock(name="customerService");
private CustomerService customerService;
@InjectMocks
private Restaurant classUnderTest;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
@Test
public void updateCustomer_WithValidInput_ShouldReturnUpdatedInput(){
//Some Mocking first
String customerId = "customerId";
Customer customer = mock(Customer.class);
CustomerInputData = mock(CustomerInputData.class);
doReturn(customer).when(customerService.getCustomerById(any(String.class)));
doReturn(customerId).when(inputData.getId());
doReturn("address").when(customer.getAddress());
doReturn("Name").when(customer.getName());
doReturn("City").when(customer.getCity());
doReturn("Language").when(customer.getLanguage());
doNothing().when(inputData).setCustomerName(any(String.class));
doNothing().when(inputData).setCustomerCity(any(String.class));
doNothing().when(inputData).setCustomerLanguage(any(String.class));
verify(customer.getAddress(), atLeastOnce());
verify(customer.getName(), atLeastOnce());
//and so on...
verify(inputData, atLeastOnce()).setCustomerName(eq("Name"));
verify(inputData, atLeastOnce()).setCustomerCity(eq("City"));
verify(inputData, atLeastOnce()).setCustomerLanguage(eq("Language");
}
}
Run Code Online (Sandbox Code Playgroud)
所以目前我没有Assert,我只检查是否调用了正确的方法.原因,为什么我尝试这样做,而不是让Test-class调用setter/getter是因为隔离.假设inputData.setCustomerCity已损坏,我的测试将失败.所以它取决于CustomerInputData-Class.
现在我如何处理这些getter和setter,最佳做法是什么?
我不明白Mockito足够好吗?当我使用mock()时,我可以只使用setter-methods和gethods,而不需要担心使用doReturns等等吗?
我知道这是一个白盒测试,我知道方法和发生了什么.
这不是“正确”的方法,因为模拟值对象被广泛认为是一种不好的做法(甚至在Mockito 的文档中也这么说)。
您的测试应该如下所示:
@Test
public void updateCustomer_WithValidInput_ShouldReturnUpdatedInput() {
String customerId = "customerId";
String name = "Name";
String address = "address";
String language = "language";
Customer customer = new Customer();
customer.setName(name);
customer.setAddress(address);
customer.setLanguage(language);
CustomerInputData inputData = new CustomerInputData();
inputData.setId(customerId);
doReturn(customer).when(customerService).getCustomerById(customerId);
CustomerInputData updatedInput = classUnderTest.updateCustomer(inputData);
assertSame(inputData, updatedInput);
assertEquals(name, updatedInput.getCustomerName());
assertEquals(address, updatedInput.getCustomerCity());
assertEquals(language, updatedInput.getLanguage());
}
Run Code Online (Sandbox Code Playgroud)
有关单元测试的精彩演示,请参阅Martin Fowler 最近的文章。
只嘲笑你无法创造或通过自己的东西. 难道不是嘲笑任何传入的实体; 提供假冒版本通常要优越得多.
在这种情况下,我们可以解决一些问题,因为我们知道有关测试的一些事情:
Customer从中获取实例customerService,但我们不需要对该实例进行任何类型的验证.customerService,因为它是一个注入的依赖.鉴于这两件事,我们应该嘲笑CustomerService你,你做了哪些成功 - 因为字段命名相同,你不需要注释中的额外元数据.
@Mock
private CustomerService customerService;
Run Code Online (Sandbox Code Playgroud)
您还应该使用Mockito提供的测试运行器,这样您就不必显式初始化模拟.
@RunWith(MockitoJUnitRunner.class)
public class RestaurantTest {
// tests
}
Run Code Online (Sandbox Code Playgroud)
现在,进行实际的单元测试.唯一真正糟糕的是你必须提供一个客户的实例来使用,但除此之外,它并不是太糟糕.我们的恩惠是CustomerData我们想要变异的例子,我们Customer提供测试.然后,我们必须简单地断言我们关心的值将返回给我们的测试CustomerData实例.
@Test
public void updateCustomer_WithValidInput_ShouldReturnUpdatedInput(){
//given
final Customer customer = new Customer();
customer.setId("123");
customer.setAddress("Addr1");
customer.setName("Bob");
customer.setCity("St8")
customer.setLanguage("Java");
final CustomerInputData inputData = new CustomerInputData();
inputData.setId(customer.getId());
//when
when(customerService.getCustomerById(customer.getId())).thenReturn(customer);
classUnderTest.updateCustomer(customerData);
//then
verify(customerService.getCustomerById("123"));
assertThat(customerData.getCustomerName(), equalTo(customer.getName()))
// and so forth
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20159 次 |
| 最近记录: |