Spring Cloud微服务实战---1.5.测试先行的开发策略

11 篇文章 1 订阅
11 篇文章 0 订阅

为了提高软件开发质量,我们需要对所开发的功能进行单元测试,在Spring Boot中,进行单元测是非常容易的。在开发过程中,认真准备单元测试用例,不仅可以保证代码质量,也便于进行回归测试。今后在修改或代码重构时,通过回归测试,可以保证修改和代码重构的正确性。
为了支持Spring下的单位测试,我们需要在pom.xml中添加依赖:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>

我们在src/test/java中创建单元测试用例,在我里我们以测试ProductController为例,先来讲解测试微服务:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ProductControllerTests {
	@Autowired
	private MockMvc mvc;
	
	@Before
	public void setUp() throws Exception {
	}

	@Test
	public void testAll() {
		try {
			mvc.perform(MockMvcRequestBuilders.get("/products").
					accept(MediaType.APPLICATION_JSON)).andExpect(new ResultMatcher() {

						@Override
						public void match(MvcResult result) throws Exception {
							System.out.println("result:" + result.getResponse().getContentAsString() + "!");
							Assert.assertEquals("1", "1");
						}});
		} catch (Exception e) {
			fail("异常:" + e.getMessage() + "!");
		}
	}

	@Test
	public void testAddProduct() {
		// Assert.assertEquals("1", "2");
		// fail("添加产品失败");
	}

	@Test
	public void testOne() {
	}

	@Test
	public void testUpdateProduct() {
	}

	@Test
	public void testDeleteProduct() {
	}

	@Test
	public void testTestJdbc() {
	}

	@Test
	public void testTestTransaction() {
	}
}

第1行:所有Spring的测试用例均需写这个注解;
第2行:测试Spring Boot微服务时必须加这个注解,会将服务启动在一个临时端口上;
第3行:测试SpringMVC时需要用到的注解;
第5、6行:测试SpringMvc时需要的对象;
第12~26行:以列出所有产品的服务为例,实现一个完整的测试用例。所有测试用例均需加@Test注解;
第15行:通过mvc发起HTTP请求;
第16行:通过andExpect函数来检查结果是否正确;
第16~22行:定义一个ResultMatcher对象,可以对响应进行检查,通过Assert系列函数,来判断服务是否正确;
可以通过类似的方式对其他服务进行相同的测试,这样当我们对服务进行修改时,我们就可以通过运行这些测试用例,保证我们的修改是正确且安全的。
选中ProductControllerTest类,点击右键选择Run as => JUnit Test,运行结果如下所示:
在这里插入图片描述
如图所示:我们可以取到响应结果,即以Json格式给出的所有产品的列表。Junit测试用例的运行结果如下所示:
在这里插入图片描述
在实际项目中,比较难于测试的,除了SpringMvc以外,就是数据库部分了。我们在项目中数据库增删改采用了JPA,而数据库查询操作采用了JdbcTemplate技术。
我们先来看JPA测试用例的编写:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ProductRepositoryTest {
	@Autowired
	ProductRepository repository;

	@Test
	@Rollback(false)
	public void test() {
		Product product = new Product();
		product.setProductName("XXXXXXXXXX");
		//fail("Not yet implemented");
		repository.save(product);
		Assert.assertEquals("1", "1");
	}

}

第1行:所有Spring的测试用例均需添加的注解;
第2行:测试JPA时需要添加的注解;
第3行:当使用真实环境数据库时需要添加的注解;
第5、6行:由于我们JPA使用ProductRepository接口,所以从Spring获取该接口的实现类的实例;
第8、9行:由于JPA测试时,所有对数据库的操作,在测试结束时会自动回滚,所以测试结束时看不到脏数据,这是一个很好的特性,测试不影响数据库正确数据。但是如果我们希望测试结束后看到数据,需要加@Rollback(false)注解;
下面我们来看JdbcTemplate的测试用例编写,由于我们的DAO实现类ProductMysqlDao是通过@Service来注解的,我们通过两种方式来进行数据库查询操作,如下所示:

	public List<ProductVo> getProducts() {
		Object[] params = new Object[1];
		params[0] = 1; // new BeanPropertyRowMapper(Account.class)
		// 方法1
		List<ProductVo> recs = jdbcTemplate.query("select product_name, image_url, price from t_product where product_category_id=?", params, new BeanPropertyRowMapper(ProductVo.class));
		// 方法2
		/*List<ProductVo> recs = jdbcTemplate.query("select product_name, image_url, price from t_product where product_category_id=?", params, (rs, num) -> {
			ProductVo vo = new ProductVo();
			vo.setProductName(rs.getString(1) + "---M2");
			return vo;
		});*/
		return recs;
	}
	

	public List<ProductVo> getProducts2() {
		Object[] params = new Object[1];
		params[0] = 1; // new BeanPropertyRowMapper(Account.class)
		// 方法1
		//List<ProductVo> recs = jdbcTemplate.query("select product_name, image_url, price from t_product where product_category_id=?", params, new BeanPropertyRowMapper(ProductVo.class));
		// 方法2
		List<ProductVo> recs = jdbcTemplate.query("select product_name, image_url, price from t_product where product_category_id=?", params, (rs, num) -> {
			ProductVo vo = new ProductVo();
			vo.setProductName(rs.getString(1) + "---M2");
			return vo;
		});
		return recs;
	}

接下来我们就来测试这两个方法,如下所示:

@RunWith(SpringRunner.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(classes = MseApplication.class)
public class ProductMysqlDaoTest {
	@Autowired
	private ProductMysqlDao dao;

	@Test
	public void testGetProducts() {
		List<ProductVo> vos = dao.getProducts();
		for (ProductVo vo : vos) {
			System.out.println("####:" + vo.getProductId() + "=>" + vo.getProductName() + "!");
		}
		Assert.assertEquals("1", "1");
	}
	
	@Test
	public void testGetProducts2() {
		List<ProductVo> vos = dao.getProducts2();
		for (ProductVo vo : vos) {
			System.out.println("####:" + vo.getProductId() + "=>" + vo.getProductName() + "!");
		}
		Assert.assertEquals("1", "1");
	}
}

在这个测试类中,我们不仅添加对JdbcTemplate的测试,而且还添加了Service层的测试,这样我们就可以对Spring应用中所有的组件进行单元测试了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值