Spring Boot web项目的TDD流程

}

然后编写请求/simples http请求的测试代码

@Test

void testFindAllSimples() throws Exception {

List simpleList = new ArrayList<>();

simpleList.add(new Simple(1L,“one”));

simpleList.add(new Simple(2L,“two”));

when(simpleService.findAll()).thenReturn(simpleList);

mockMvc.perform(MockMvcRequestBuilders.get(“/simples”)

.contentType(MediaType.APPLICATION_JSON)).andExpect(jsonPath(“$”, hasSize(2))).andDo(print());

}

when then结构来自Mockito框架,when表示了执行的条件,then用于执行验证,这里的操作对simpleService.findAll方法结果进行了mock,这里 在这一层不需关心的simpleService的真实实现。后面perform方法 mock了 /simples的请求。

这里报错,红灯,接下来编写Simple类的实现。

@Entity

public class Simple {

private Long id;

private String desc;

public Simple(String desc) {

this.desc = desc;

}

}

因为simpleService.findAll方法未定义,所以还是报错的,红灯。接下来保持简单,给SimpleService创建一个findAll方法。

public List findAll() {

return new ArrayList<>();

}

编译问题都解决了,下面开始运行测试代码。

报错,

java.lang.AssertionError: No value at JSON path “$”

还是红灯,这是因为我们mock的perform 没有存在。接下来创建一个SimpleController类作为RestController,并编写/simples请求的接口。

@RestController

public class SimpleController {

@Autowired

private SimpleService simpleService;

@GetMapping(“/simples”)

public ResponseEntity<List> getAllSimples() {

return new ResponseEntity<>(simpleService.findAll(), HttpStatus.OK);

}

}

再次运行测试用例,测试都通过了,绿灯。

2 Service

=========

接下来让我们关注Service层的代码测试,test代码区创建一个SimpleServiceTest类。该类对下一层Repository依赖,同样的,创建一个Repository的mock对象。

@SpringBootTest

public class SimpleServiceTest {

@MockBean

private SimpleRepository simpleRepository;

}

编译报错,红灯,需要创建一个SimpleRepository。

@Repository

public interface SimpleRepository extends JpaRepository<Simple,Long> {

}

以上,创建SimpleRepository作为实体Simple类对象的JPA存储服务。

编写测试代码

@Test

void testFindAll() {

Simple simple = new Simple(“one”);

simpleRepository.save(simple);

SimpleService simpleService = new SimpleService(simpleRepository);

List simples = simpleService.findAll();

Simple entity = simples.get(simples.size() - 1);

assertEquals(simple.getDesc(),entity.getDesc());

assertEquals(simple.getId(),entity.getId());

}

继续解决编译报错的问题,SimpleService没有构造方法。添加Repository 并注入bean。

@Service

public class SimpleService {

private SimpleRepository simpleRepository;

public SimpleService(SimpleRepository simpleRepository) {

this.simpleRepository = simpleRepository;

}

public List findAll() {

return new ArrayList<>();

}

}

这里插播一个题外话,为啥Spring推荐通过构造方法的方式注入bean, 方便编写可测试代码是个重要原因。

运行测试用例,会继续报错,这里是因为JPA hibernate没有和实体类对象交互,需要添加主键注解,默认构造函数 getter/setter 重新编写实体类的代码。

@Entity

public class Simple {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String desc;

public Simple() {

}

public Simple(String desc) {

this.desc = desc;

}

// 省略 getter/setter …

}

修改完毕之后 运行测试用例 依然失败,findAll方法测试未通过,修改SimpleService的findAll方法,调用 jpa repository的findAll方法

public List findAll() {

return simpleRepository.findAll();

}

现在再次运行测试用例,测试通过。

3 Repository

============

前面已经通过了TDD去实现Controller层和Service层的代码,理论上Repository实现了JPA的接口,我们没有做任何代码的编写,应该不需要进行测试,但是我们不确定数据是否通过数据库进行了存储和查询。为了保证数据库存储,将真正的JPA respoitory实例注入的Service对象中。修改@MockBean 为@Autowired。

@SpringBootTest

public class SimpleServiceTest {

@Autowired

private SimpleRepository simpleRepository;

@Test

void testFindAll() {

Simple simple = new Simple(“one”);

simpleRepository.save(simple);

SimpleService simpleService = new SimpleService(simpleRepository);

List simpleEntities = simpleService.findAll();

Simple entity = simpleEntities.get(simpleEntities.size() - 1);

assertEquals(simple.getDesc(),entity.getDesc());

assertEquals(simple.getId(),entity.getId());

}

}

创建H2 database配置。

classpath下 创建schema.sql和data.sql,创建表和插入一点数据。

#H2 Begin****

#创建表的MySql语句位置

spring.datasource.schema=classpath:schema.sql

#插入数据的MySql语句的位置

spring.datasource.data=classpath:data.sql

禁止自动根据entity创建表结构,表结构由schema.sql控制

spring.jpa.hibernate.ddl-auto=none

spring.jpa.show-sql=true

schema.sql

DROP TABLE IF EXISTS simple;

CREATE TABLE simple (

id BIGINT(20) auto_increment,

desc varchar(255)

);

data.sql

INSERT INTO simple(desc) VALUES (‘test1’);

INSERT INTO simple(desc) VALUES (‘test2’);

继续运行测试用例,所有用例都测试通过,浏览器直接访问localhost:8080/simples

返回data.sql插入的数据

[

最后

由于篇幅限制,小编在此截出几张知识讲解的图解

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

P8级大佬整理在Github上45K+star手册,吃透消化,面试跳槽不心慌

ata.sql

INSERT INTO simple(desc) VALUES (‘test1’);

INSERT INTO simple(desc) VALUES (‘test2’);

继续运行测试用例,所有用例都测试通过,浏览器直接访问localhost:8080/simples

返回data.sql插入的数据

[

最后

由于篇幅限制,小编在此截出几张知识讲解的图解

[外链图片转存中…(img-G15DBeof-1714449303785)]

[外链图片转存中…(img-w0HnS2qm-1714449303786)]

[外链图片转存中…(img-1Sq0hXjt-1714449303786)]

[外链图片转存中…(img-0ypaFrCY-1714449303786)]

[外链图片转存中…(img-4szvl3Mc-1714449303787)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值