java - 如何对 Spring 存储库进行单元测试

标签 java unit-testing spring-boot

我创建了一个 springboot 项目,分为三个 Maven 模块:领域层、核心层(包含持久性和业务逻辑)和 Web 层。我尝试对我的存储库 ProductRepository (位于核心层)进行单元测试

@RunWith(SpringRunner.class) // provide bridge between SpringBoot test features and JUnit, for usage of springboot tsting features
@DataJpaTest
class ProductRepositoryTest {
	@Autowired
	private TestEntityManager em;
	@Autowired
	private ProductRepository repository;
	

	@Test
	void shouldReturnProduct() {
		// given
		Product p = Product.builder().id(1).designation("Test").reference("TEST").unitPrice(150).build();
		this.em.persistAndFlush(p);
		// when
		Product found = repository.findByReference(p.getReference());
		// then
		assertThat(found.getReference()).isEqualTo(p.getReference());
	}

}

但是存储库始终实例化为 null。我在 Eclipse 中将这个测试作为 JUnit Test 运行,并且得到了一个 nullpointerException。

这是我的 pom.xml 文件

<dependencies>
		<!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> 
			</dependency> -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency> 
	</dependencies>

最佳答案

你说你尝试对 Controller 进行单元测试,但你使用@RunWith(SpringRunner.class),这用于集成测试。该注释启动完整的应用程序。您只想测试存储库。您可以做的是创建一个抽象 DAO,您可以在单元测试中实现它。

public abstract class AbstractRepository<RepositoryType> {
RepositoryType repository;
private DBI dbi;

protected abstract RepositoryType createRepository(final DBI dbi);

@Before
public final void setUpDataSource() throws Exception {
    final JdbcDataSource jdbcDataSource = new JdbcDataSource();
    // DB_CLOSE_DELAY=-1 ==> h2 will keep its content as long as the vm lives otherwise the content of the database
    // is lost at the moment the last connection is closed.
    jdbcDataSource
            .setURL("jdbc:h2:mem:play;MODE=MySQL;DB_CLOSE_DELAY=-1L;INIT=RUNSCRIPT FROM 'classpath:path/to/file/init_test.sql';");

    final Flyway flyway = new Flyway();
    flyway.setDataSource(jdbcDataSource);
    flyway.setLocations("/path/to/locations");
    flyway.migrate();

    dbi = new DBI(jdbcDataSource);

    runDbScript("/data.sql");

    repository = createRepository(dbi);
}

private void runDbScript(final String scriptPath) throws Exception {
    try (InputStreamReader reader = new InputStreamReader(AbstractDaoTest.class.getResourceAsStream(scriptPath),
            Charsets.UTF_8); Handle h = dbi.open()) {
        RunScript.execute(h.getConnection(), reader);
    }
}

}

现在您可以覆盖测试类中的 createRepository 方法。

public class ProductRepositoryTest() { 

@Override
protected ProductRepository createRepository(Dbi dbi) { return new ProductRepository(dbi); }

@Test
public void testGetProductById() {

    Product response = repository.getProductById(1);
    assertThat(response).isEqualTo(someObject);
    }    
}

如果您需要一个框架来模拟对象,您可以使用 Mockito,如果您需要模拟静态或 void 方法,您可以使用 PowerMock。

希望这有帮助。

关于java - 如何对 Spring 存储库进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51772890/

相关文章:

java - 如何更改 MaterialCalendarView 中日历日期的背景颜色

unit-testing - 使用 doWithSpring 注入(inject)模拟

javascript - enzyme 和 Mocha 给我 Istanbul 尔覆盖测试的错误,为什么?

java - Spring启动与Spring安全错误: There was an unexpected error (type=Forbidden,状态= 403)

java - Spring boot - 从外部类路径加载文件

java - 将读取同步到 java 集合

java - 将私有(private)方法设为静态以增加函数式编程的习惯

java - 为什么向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中?

java - 在测试环境中解析异常,而在 Android 环境中工作正常

java.sql.SQLIntegrityConstraintViolationException Spring 启动