spring-boot:测试@service类

时间:2016-09-11 11:36:04

标签: java testing spring-boot

我对Spring Boot和测试有点新鲜。我想测试这个@Service类:

@Service
public class TransactionService {

    private MessagingService messagingService;
    private CustomerRepository customerRepository;

    private static final Logger log = LoggerFactory.getLogger(TransactionService.class);

    @Autowired
    public TransactionService(MessagingService messagingService, CustomerRepository customerRepository){
        Assert.notNull(messagingService, "MessagingService cannot be null");
        this.messagingService = messagingService;
        Assert.notNull(customerRepository, "CustomerRepository cannot be null");
        this.customerRepository = customerRepository;
    }

    public void makeTransactionFromSenderToReceiver(Customer sender, Customer receiver, int amount) {

        if (sender.getBalance() >= amount) {
            sender.setBalance(sender.getBalance() - amount);
            receiver.setBalance(receiver.getBalance() + amount);

            customerRepository.save(sender);
            customerRepository.save(receiver);
        }

        else {
            throw new CustomerBalanceExceededException();
        }
    }
}

在我的武器库中,我有测试的spring-boot-starter-test maven依赖。我设法像这样测试我的Customer类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class CustomerTests
{
  @Autowired
  private CustomerRepository repository;

  @Test
  public void testCreate()
  {
    final Customer customer = new Customer();
    customer.setName("CoolGuy");

    Assert.notNull(repository.save(customer));
  }
}

我目前不知道如何测试上面定义的@Service类的方法的功能。任何提示都非常赞赏。

编辑:我曾尝试编写测试,但我认为这不是测试此逻辑的正确方法。任何帮助将不胜感激:

TransactionServiceTests.class

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class TransactionServiceTests {

    @Autowired
    private CustomerRepository repository;

    @Autowired
    private TransactionService transactionService;

    @Test
    public void testTransactionBetweenCustomersAndBalanceOfReceiver() {

        int AMOUNT = 50;

        Customer customerOksana = repository.findByName("Oksana");
        Customer customerDeniss = repository.findByName("Deniss");

        transactionService.makeTransactionFromSenderToReceiver(customerDeniss, customerOksana, AMOUNT);
        assertThat(customerOksana.getBalance()).isEqualTo(customerOksana.getBalance());
    }

    @Test
    public void testTransactionBetweenCustomersAndBalanceOfSender() {

        int AMOUNT = 40;

        Customer customerOksana = repository.findByName("Oksana");
        Customer customerDeniss = repository.findByName("Deniss");

        transactionService.makeTransactionFromSenderToReceiver(customerDeniss, customerOksana, AMOUNT);
        assertThat(customerDeniss.getBalance()).isEqualTo(customerDeniss.getBalance());
    }
}

1 个答案:

答案 0 :(得分:2)

单元测试,请参阅Mockito或其他一些模拟框架。您甚至不应该在测试类本身上需要任何注释。您希望测试方法调用并验证与其他类的交互和结果是否符合您的预期。

以下是使用Mockito进行单元测试的示例。显然你想要充实它并添加更多测试。这将为您提供代码覆盖,并验证前后条件。这不会测试存储库代码是否正确映射,或者事务边界是否按预期工作,这必须使用集成测试来完成。

public class TransactionServiceTest {

    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock
    private MessagingService mockMessagingService;
    @Mock
    private CustomerRepository mockCustomerRepository;

    @Test
    public void testMakeTransactionFromSenderToReceiver() {
        // setup the state of the sender and receiver
        Customer sender = new Customer();
        sender.setBalance(5.0);
        Customer receiver = new Customer();
        receiver.setBalance(10.0);
        TransactionService transactionService = new TransactionService(mockMessagingService, mockCustomerRepository);

        transactionService.makeTransactionFromSenderToReceiver(sender, receiver);

        // assert the expected state of the Customer objects
        assertEquals(1.0, sender.getBalance());
        assertEquals(1.0, receiver.getBalance());

        // verify that the repositories were called appropriately once
        // this can be made to be more specific and check the argument that was passed - see Mockito documentation
        verify(mockCustomerRepository, times(2)).save(any());
    }

}

断言的逻辑不正确

@Test
public void testTransactionBetweenCustomersAndBalanceOfReceiver() {

    int AMOUNT = 50;

    Customer customerOksana = repository.findByName("Oksana");
    Customer customerDeniss = repository.findByName("Deniss");

    transactionService.makeTransactionFromSenderToReceiver(customerDeniss, customerOksana, AMOUNT);
    assertThat(customerOksana.getBalance()).isEqualTo(customerOksana.getBalance());
}

您声称同一实例具有相同的余额。这将永远是真的。您希望通过将新客户保存到存储库或在执行方法makeTransactionFromSenderToReceiver之前获取原始余额来检查调整是否符合预期。

@Test
public void testTransactionBetweenCustomersAndBalanceOfReceiver() {

    int AMOUNT = 50;

    // prepare your test data unless you always expect those values to exist.
    Customer customerReceiver = new Customer();
    customerReciever.setName("Oksana");
    customerReceiver.setBalance(12);
    customerReceiver = repository.save(customerReceiver);

    Customer customerSender = new Customer();
    customerSender.setName("Deniss");
    customerSender.setBalance(5);
    customerSender = repository.save(customerSender);

    // assign before executing method
    int expectedReceiverAmount = customerReceiver.getBalance() + AMOUNT;
    int expectedSenderAmount = customerSender.getBalance() - AMOUNT;
    transactionService.makeTransactionFromSenderToReceiver(customerSender, customerReceiver, AMOUNT);

    assertEquals(expectedSenderAmount, customerSender.getBalance());
    assertEquals(expectedReceiverAmount, customerReceiver.getBalance());
}