2

This is a very simplified version of my code, that illustrates the specific problem.

Is there any way that I can control what happens when accountProductRepository.refresh() is called from the test?

Somehow I need to set the ProductPojo on the AccountProductPojo created in the buyProduct() method, so I don't get a null pointer when accessing the getProduct().getName() property.

refresh uses javax.persistence.EntityManager.refresh() to load the navigation properties based on the id's set in the buyProduct() method.

public class ProductServiceTest {
    @InjectMocks
    IProductService productService = new ProductService();
    @Mock
    IWriteANoteService writeANoteService;
    @Mock
    IAccountProductRepository accountProductRepository;

    @Test
    public void buyProductTest() {
        productService.buyProduct(1l, 1l);
    }
}

@Service
public class ProductService implements IProductService {
    @Autowired
    IWriteANoteService writeANoteService;

    @Autowired
    IAccountProductRepository accountProductRepository:

    public void buyProduct(Long productId, Long accountId) {
        AccountProductPojo accountProduct = new AccountProductPojo();
        accountProduct.setProductId(productId);
        accountProduct.setAccountId(accountId);

        accountProductRepository.persist(accountProduct);
        // load navigation properties
        accountProductRepository.refresh(accountProduct);

        writeANoteService.writeAccountNote(accountId, "Bought product " + accountProduct.getProduct().getName());
    }
}

@Entity
@Table(name = "account_product")
public class AccountProductPojo {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "account_id")
    private Long accountId;

    @Column(name = "product_id")
    private Integer productId;

    @ManyToOne
    @JoinColumn(name = "product_id", insertable = false, updatable = false)
    private ProductPojo product;

    @OneToOne(fetch = FetchType.LAZY, targetEntity = AccountPojo.class)
    @JoinColumn(name = "account_id", insertable = false, updatable = false)
    private AccountPojo account;

    // getters and setters
}
heuts
  • 117
  • 1
  • 12

1 Answers1

2

This seems to be a fairly classic case of mocking a void method.

You could try something like this:

    Mockito.doAnswer(new Answer() {
          public Object answer(InvocationOnMock invocation) {
              Object[] args = invocation.getArguments();
              AccountProductPojo accountProduct = (AccountProductPojo) args[0];
              accountProduct.setProduct(new ProductPojo(PRODUCT_ID_CONSTANT, PRODUCT_NAME_CONSTANT));
              return null;
          }}).when(accountProductRepository).refresh(Mockito.any());

The key here is that when refresh() is called on the mock you call setProduct() on the POJO which was passed as an argument to the refresh() call in order to avoid the later null pointer exception.

Community
  • 1
  • 1
aro_tech
  • 1,103
  • 7
  • 20