【发布时间】:2016-06-08 09:07:49
【问题描述】:
我的 Spring Boot 应用有以下类:
董事会(JPA 实体)
@Entity
@Table(name = "board")
public class Board {
public static final int IN_PROGRESS = 1;
public static final int AFK = 2;
public static final int COMPLETED = 3;
@Column(name = "id")
@Generated(GenerationTime.INSERT)
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@Column(name = "status", nullable = false)
private int status = IN_PROGRESS;
}
BoardRepository(JPA 存储库)
public interface BoardRepository extends JpaRepository<Board, Long> {}
CommonBoardService(基础服务)
public interface CommonBoardService {
Board save(Board board);
Board update(Board board, int status);
}
CommonBoardServiceImpl(基础服务实现)
@Service
@Transactional
public class CommonBoardServiceImpl implements CommonBoardService {
@Autowired
private BoardRepository boardRepository;
public Board save(final Board board) {
return boardRepository.save(board);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Board update(final Board board, final int status) {
board.setStatus(status);
return save(board);
}
}
BoardService(具体服务接口)
public interface BoardService {
Board startBoard();
void synchronizeBoardState(Board board);
}
BoardServiceImpl(具体服务实现)
@Service
@Transactional
public class BoardServiceImpl implements BoardService {
@Autowired
private CommonBoardService commonBoardService;
public Board startBoard() { return new Board(); }
public void synchronizeBoardState(final Board board) {
if (board != null && inProgress(board)) {
if (!canPlayWithCurrentBoard(board)) {
commonBoardService.update(board, Board.AFK);
}
else {
commonBoardService.update(board, Board.COMPLETED);
}
}
}
private boolean canPlayWithCurrentBoard(final Board board) {
return !inProgress(board);
}
private boolean inProgress(final Board board) {
return board != null && board.getStatus() == Board.IN_PROGRESS;
}
}
BoardServiceTest(单元测试)
1. @RunWith(SpringJUnit4ClassRunner.class)
2. @Transactional
3. public class BoardServiceTest {
4. @Autowired
5. private BoardRepository boardRepository;
6.
7. @Autowired
8. private BoardService boardService;
9. @Autowired
10. private CommonBoardService commonBoardService;
11.
12. @Test
13. public void testSynchronizeBoardStatus() {
14. Board board = boardService.startBoard();
15.
16. board = commonBoardService.save(board);
17.
18. assertEquals(1, boardRepository.count());
19.
20. boardService.synchronizeBoardState(board);
21.
22. assertEquals(1, boardRepository.count());
23. }
24. }
此测试在第 22 行失败,错误为 java.lang.AssertionError: Expected :1 Actual:2。 Hibernate SQL 日志显示在第 20 行触发了 INSERT,而不是 UPDATE。由于我在整个测试过程中使用相同的 Board 对象,因此我希望第 20 行会触发 UPDATE 而不是 INSERT。
谁能解释为什么会发生这种情况以及如何获得预期的行为(第 20 行的UPDATE)?
【问题讨论】:
-
您的 TestDataSourceConfiguration.class 指向哪个数据库?它是否有您要更新的董事会实体?
-
BoardServiceTest中的boardService和commonBoardService是什么?boardService.startBoard(admin)和commonBoardService.save(board)看起来像什么?大概,第一个是创建一个新的board,第二个是保存它?另外,Board和User类的代码是什么样的?如果您可以创建一个演示问题的小示例可能会更好,因为要涵盖的代码非常多。 -
@koder23,感谢您的回复。我正在使用postgres。是的,它应该有
Board board = boardService.startBoard(admin);- 创建新的板,实体的 ID 等于 1。 -
你能贴出完整的代码来测试一下吗?仍有许多部分缺失,难以重现问题。可以在 Github 上发布示例应用吗?
-
@manish,你是对的,
boardService.startBoard(admin)- 为用户创建新版块。如您所见,boardService.synchronizeBoardState(board, admin)有不同的检查。所以,我想在我们进入if (!canPlayWithCurrentBoard(board))代码块时触发这个案例。为此,我需要更新board实体以满足这些条件。这就是我在测试中使用commonBoardService.save(board)的原因。