开发者社区> 问答> 正文

使用List属性测试Bean时出现问题

大家好,这是我的项目:

两个实体通过某种@OneToMany关系相互联系:

@Entity
public class Brand {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    @NotNull(message = "Brand can not have empty name.")
    private String name;

    @Column
    private String description;

    @OneToMany(mappedBy="brand"
    , cascade= {CascadeType.DETACH,
            CascadeType.MERGE,
            CascadeType.PERSIST,
            CascadeType.REFRESH},
    fetch = FetchType.EAGER)    
    @OrderBy("price ASC") // order products by price
    private List<Product> productList;

    // getters and setter following here ...
}

@Entity
public class Product {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    @NotNull(message = "Product can not have empty name.")
    private String name;

    @Column
    private Double price;

    @Column
    private Boolean onSale=false;

    @ManyToOne(cascade= {CascadeType.DETACH,
            CascadeType.MERGE,
            CascadeType.PERSIST,
            CascadeType.REFRESH})
    @JoinColumn(name="brand_id", nullable=false)
    private Brand brand;

 // getters and setter following here ...
}

package com.microservices.product.datatranferobject;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;


@JsonInclude(JsonInclude.Include.NON_NULL)
public class ProductDTO {

    private Long id;

    private String name;    

    private Double price;   

    @JsonIgnore // omit this property when exposing data over the API
    private Boolean onSale;

    private String event;

    public ProductDTO() {

    }    

    public ProductDTO(Long id, String name, Double price, String event, Boolean onSale) {
        super();
        this.id = id;
        this.name = name;
        this.price = price;
        this.event = event;
        this.onSale=onSale;
    }

    public Boolean getOnSale() {
        return onSale;
    }

    public void setOnSale(Boolean onSale) {
        this.onSale = onSale;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getEvent() {
        return onSale?"ON SALE":null;
    }

    public void setEvent(String event) {
        this.event = event;
    }    

}


public class BrandDTO {
    private String name;

    private List<ProductDTO> productList;

    public BrandDTO() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<ProductDTO> getProductList() {
        return productList;
    }

    public void setProductList(List<ProductDTO> productList) {
        this.productList = productList;
    }   
}

一个简单的DAO类:

public interface BrandRepository extends JpaRepository<Brand, Long>{

    List<Brand> findAllByOrderByName();
}

一个简单的服务:

public interface BrandService {

    List<Brand> getAllBrands(); 
}

@Service
public class BrandServiceImpl implements BrandService {

    @Autowired
    BrandRepository myBrandRepo;

    @Override
    public List<Brand> getAllBrands(){
        return myBrandRepo.findAllByOrderByName();
    }   
}

和一个控制器,该控制器使用我自定义的编程Mapper将产品映射到ProductDTO:

public class ModelMapper {
    public static BrandDTO makeBrandDTO(Brand myBrand)
    {
        BrandDTO myBrandDTO=new BrandDTO();

        org.modelmapper.ModelMapper myStandardMapper=new org.modelmapper.ModelMapper();

        List<ProductDTO> myProductsList=myBrand.getProductList()
                .stream()
                .map(product->myStandardMapper.map(product, ProductDTO.class))
                .collect(Collectors.toList());
        myBrandDTO.setProductList(myProductsList);

        myBrandDTO.setName(myBrand.getName());

        return myBrandDTO;
    }
}


@RestController
@RequestMapping("v1/search")
public class BrandController {

    @Autowired
    BrandService myBrandService;

    @GetMapping("/get/products/")
    public Map<String, List<ProductDTO>> getAllProductsMap(){

        List<BrandDTO> myList= myBrandService.getAllBrands()
        .stream().map(brand->ModelMapper.makeBrandDTO(brand))
        .collect(Collectors.toList());      

        Map<String, List<ProductDTO>> myMap=new TreeMap<String, List<ProductDTO>> ();

        myList.forEach(brand->myMap.put(brand.getName(), brand.getProductList()));

        return myMap;
    }

}

ProductDTO与Product实体完全相同,因此我将节省时间并写下来。

因此,问题来了。我正在使用Junit来测试我的Controller,并让以下类运行测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProductApplication.class,webEnvironment=WebEnvironment.RANDOM_PORT)
public class ControllerLayerTester {

    private static Log myLogger = LogFactory.getLog(ControllerLayerTester.class);

    private static RestTemplate restTemplate;

    private static HttpHeaders headers;

    @LocalServerPort
    private int port;

    @BeforeClass
    public static void runBeforeAllTestMethods() {

        restTemplate = new RestTemplate();
        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

    }

    /**
     * simple test to verify the given requirements
     */
    @Test
    public void testBrandListIsOrdered() {

        TreeMap<String, List<ProductDTO>> productList=restTemplate.getForObject("http://localhost:"+port+"/v1/search/get/products/",TreeMap.class);

        for (List<ProductDTO> myProductList:productList.values()) {

            myProductList.forEach(product->assertTrue(product.getId()!=null));

        }
    }

}

当我运行它时,出现以下错误:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.microservices.product.datatranferobject.ProductDTO
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at com.microservices.product.ControllerLayerTester.testBrandListIsOrdered(ControllerLayerTester.java:81)

我在这里做错什么了吗?为什么不让列表填充我的实体,而是填充LinkedHashMaps?是否有解决方案以获得产品列表?

编辑:

我还在这里提供我的项目依赖关系,我在帖子的顶部还添加了DTO:

buildscript {
    ext {
        springBootVersion = '2.1.0.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.microservices'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
    implementation('org.springframework.boot:spring-boot-starter-web')
    compile("org.springframework.boot:spring-boot-devtools")
    compile group: 'org.modelmapper', name: 'modelmapper', version: '2.1.0'
    runtimeOnly('com.h2database:h2')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
    testImplementation 'org.assertj:assertj-core:3.15.0'
    compile group: 'com.google.guava', name: 'guava', version: '23.5-jre'
    compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0'
    compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0' 
}

问题来源:Stack Overflow

展开
收起
montos 2020-03-22 08:41:36 1075 0
1 条回答
写回答
取消 提交回答
  • 问题是TreeMap<String, List<ProductDTO>>无法从TreeMap.class内部推断参数化restTemplate.getForObject(...) 您将要使用更通用的版本:

    restTemplate.exchange(
        "http://localhost:"+port+"/v1/search/get/products/",
        HttpMethod.GET,
        new HttpEntity<>(null, headers),
        new ParameterizedTypeReference<TreeMap<String, List<ProductDTO>>() {}
    )
    

    回答来源:Stack Overflow

    2020-03-22 08:42:23
    赞同 展开评论 打赏
问答分类:
API
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
移动互联网测试到质量的转变 立即下载
给ITer的技术实战进阶课-阿里CIO学院独家教材(四) 立即下载
F2etest — 多浏览器兼容性测试整体解决方案 立即下载