【问题标题】:Unit Testing Hibernate with DB, test returns nullpointerexception使用 DB 进行单元测试休眠,测试返回 nullpointerexception
【发布时间】:2017-10-16 20:07:29
【问题描述】:

我用 ORM (Hibernate) 编写了 Rest Api,现在我想测试该服务逻辑。 我正在尝试模拟我的数据库的实体,但我没有出色的结果。 我的选择是用 Mockito 来解决这个问题,但现在我对此表示怀疑。 通常我从我写的测试中得到 NullPointerException 。我应该以另一种方式编写 Junit 测试(“模拟”该数据库的不同方式)还是我不了解 Hibernate?

这是我的代码: 测试类

public class ItemServiceImplTest {

@Spy
private ItemServiceImplementation itemServImpl;

@Mock
private BasketRepository basketRepository;
@Mock
private ItemRepository itemRepository;
@Mock
private Basket basket;
@Spy
private Item item;

@Before
public void setupMock() {

    MockitoAnnotations.initMocks(this);
    itemServImpl = new ItemServiceImplementation();
    itemServImpl.setItemRepository(itemRepository);
    itemServImpl.setBasketRepository(basketRepository);

}


@Test
public void testShowBasket() {
    Iterable<Basket> element = basketRepository.findAll();

    when(itemServImpl.showBasket()).thenReturn(element);

    Iterable<Basket> elementOne = itemServImpl.showBasket();

    assertThat(elementOne, is(equalTo(element)));
}


@Test
public void testAddToBasketStringInt() {
    Item a = new Item("A", 40, 70, 3);
    Basket testObjOne = new Basket(3, 70, a);

    when(itemServImpl.addToBasket("A", 3)).thenReturn((Iterable<Basket>) basketRepository.save(testObjOne));

    Iterable<Basket> zzz = itemServImpl.addToBasket("A", 3);

    assertThat(zzz, is(equalTo(testObjOne)));
}

型号

@Entity
public class Item {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String name;
private int price;
private int specialPrice;
private int qtyToDiscount;

public Item(){};



public Item(String name, int price, int specialPrice, int qtyToDiscount) {

    this.name = name;
    this.price = price;
    this.specialPrice = specialPrice;
    this.qtyToDiscount = qtyToDiscount;
}

@Entity
public class Basket {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long orderId;
private int quantity;
private int cost;



@OneToOne
@JoinTable(name = "BASKET_ORDERS", joinColumns = { @JoinColumn(name = "ORDER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ID") })
private Item item;

public Basket() {
}

public Basket(int quantity, int cost,Item items) {

    this.quantity = quantity;
    this.cost = cost;
    this.item = items;
}

服务

@Service("itemService")
@Transactional
public class ItemServiceImplementation implements ItemCRUDService, ItemCostService, ItemFindService {



public static final Logger logger = LoggerFactory.getLogger(ItemServiceImplementation.class);

@Autowired
public void setItemRepository(ItemRepository itemRepository) {
    this.itemRepository = itemRepository;
}
@Autowired
public void setBasketRepository(BasketRepository basketRepository) {
    this.basketRepository = basketRepository;
}

private BasketRepository basketRepository;

private ItemRepository itemRepository;


public Iterable<Basket> showBasket() {

    return basketRepository.findAll();
}


public Iterable<Basket> addToBasket(String name, int qty) {

        if (basketRepository.exists(itemRepository.findOne(findItem(name).getId()).getId())==false) { 

        logger.info("add to empty list");
        basketRepository.save(new Basket(qty, itemCost(name, qty), findItem(name)));
        logger.info("adding");
    }

    modifyOrder(findItem(name).getId(), qty);
    itemCost(name, qty);
    logger.info("modify");

    return showBasket();

}
public Item findItem(String name) {

    for (Item item : itemRepository.findAll()) {
        if (item.getName().equals(name)) {
            return item;
        }
    }
    return null;
}
public int itemCost(String name, int qty) {

    int price = 0;

    int modulo = qty % findItem(name).getSpecialPrice();

    price = findItem(name).getPrice() * modulo
            + findItem(name).getSpecialPrice() * ((qty - modulo) / `findItem(name).getSpecialPrice());`

    return price;

}

【问题讨论】:

  • 您似乎正在将 Mockito 为您创建的 ItemServiceImplementation 替换为一个新的,而不是间谍。您应该删除setUpMock() 的第二行。
  • 您是否考虑过使用 H2 作为真正的内存数据库,而不是模拟您的数据库操作的复杂模拟?您准备测试数据而不是模拟,并且可以使用普通的黑盒服务调用测试而不是深入研究您的实现(因此防止任何简单的重构)。
  • 谢谢大家的建议。最后,在使用 mockito 进行了几次尝试后,我使用 H2 测试了我的项目(成功)。

标签: java hibernate unit-testing spring-boot mockito


【解决方案1】:

我是否应该以另一种方式编写 Junit 测试(“模拟”的不同方式 那个数据库)

您没有提到您在生产中使用的是什么数据库,但如果它是传统的基于 SQL 的数据库,您可以使用 H2HSQL 嵌入式数据库在它们的一种兼容模式中为您的单元测试(如果您将嵌入式连接设置为默认弹簧配置文件的数据源,我发现这是最简单的方法)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-19
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    相关资源
    最近更新 更多