为了账号安全,请及时绑定邮箱和手机立即绑定

将元素添加到模拟列表

将元素添加到模拟列表

白衣非少年 2023-05-24 14:45:15
我正在尝试对负责添加到地图分类书籍的方法进行单元测试。@Servicepublic class BookService {    private final List<BookServiceSource> sources;    @Autowired    public BookService(List<BookServiceSource> sources) {        this.sources = sources;    }    public Map<Bookstore, List<Book>> getBooksByCategory(CategoryType category) {        return sources.stream()                .collect(Collectors.toMap(BookServiceSource::getName,                        source -> source.getBooksByCategory(category)));    }    }BookSerivceSource是一个接口。该接口由两个类实现。我只提供一个,因为第二个非常相似。Jsoup连接器:package bookstore.scraper.utilities;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class JSoupConnector {    public Document connect(String url) {        try {            return Jsoup.connect(url).get();        } catch (IOException e) {            throw new IllegalArgumentException("Cannot connect to" + url);        }    }}属性类:package bookstore.scraper.urlproperties;import lombok.Getter;import lombok.Setter;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Getter@Setter@Component@ConfigurationProperties("external.library.url.empik")public class EmpikUrlProperties {    private String mostPreciseBook;    private String bestSellers;    private String concreteBook;    private String romances;    private String biographies;    private String crime;    private String guides;    private String fantasy;}在调试测试时,我看到大小sources为 0。我应该如何将模拟对象添加到源列表中,或者您能告诉我是否有更好的方法吗?
查看完整描述

3 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

如前所述,不要尝试模拟该List对象。

通常也避免为您可以简单地自己创建的对象创建模拟,并尝试将自己限制为仅模拟依赖项。


测试的简化版本可能如下所示:


由于您的测试涵盖的内容比Unit BookService 我决定在这个例子中将其最小化。


您可能希望在针对特定实现的测试中执行所有其他操作。


@Test

public void getBooksByCategory() {


    List<Book> empikBestsellers = EmpikBookProvider.prepare5Bestsellers();

    List<Book> merlinBestsellers = MerlinBookProvider.prepare5Bestsellers();


    BookServiceSource bookServiceSource1 = Mockito.mock(BookServiceSource.class);

    Mockito.when(bookServiceSource1.getName()).thenReturn(Bookstore.EMPIK);

    Mockito.when(bookServiceSource1.getBooksByCategory(CategoryType.CRIME)).thenReturn(empikBestsellers);   


    BookServiceSource bookServiceSource2 = Mockito.mock(BookServiceSource.class);

    Mockito.when(bookServiceSource2.getName()).thenReturn(Bookstore.MERLIN);

    Mockito.when(bookServiceSource2.getBooksByCategory(CategoryType.CRIME)).thenReturn(merlinBestsellers);      


    List<BookServiceSource> sources = new ArrayList<>();

    sources.add(bookServiceSource1);

    sources.add(bookServiceSource2);


    BookService service = new BookService(sources);

    Map<Bookstore, List<Book>> actualMap = service.getBooksByCategory(CategoryType.CRIME);


    // compare result

}


查看完整回答
反对 回复 2023-05-24
?
繁花如伊

TA贡献2012条经验 获得超12个赞

我认为您不应该嘲笑 BookServiceSource 列表,因为您添加的内容不会执行任何操作,因为它不是真正的列表。

如果可以的话,不应该使用它,它有静默失败的倾向。

我试图提出的另一点是您正在使用模拟列表,因此当它被告知添加元素时它不会。

您可以使用两种解决问题的方法。首先,您可以为 BookServiceSources 流创建 when thenreturn,而不是推荐的解决方案。

其次,更好的方法是创建一个使用 @Before 注释创建 BookService 的 testSetup 方法。

@Before

public void testSetup(){

 List<BookServiceSource> list = new LinkedList<>();

 list.add(merlinSource);

 list.add(empikSource);

 bookService = new BookService(list);

}



查看完整回答
反对 回复 2023-05-24
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

尝试@Spy。它允许您注入您自己初始化的列表的实际实例,也可以部分模拟。

@Spy
private List<BookServiceSource> sources = new ArrayList<>();

似乎您为列表使用了不同的名称,更喜欢使用注入模拟字段的 smae 名称;消息来源

这里有很好的解释。

5. Mockito 中的模拟与间谍

当 Mockito 创建一个模拟时——它是从一个类型的类中创建的,而不是从一个实际的实例中创建的。模拟只是创建了类的一个基本的 shell 实例,完全用于跟踪与它的交互。

另一方面,间谍将包装现有实例。它仍将以与普通实例相同的方式运行——唯一的区别是它还将被检测以跟踪与其进行的所有交互。


查看完整回答
反对 回复 2023-05-24
  • 3 回答
  • 0 关注
  • 111 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信