将元素添加到模拟列表

我正在尝试对负责添加到地图分类书籍的方法进行单元测试。


@Service

public 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;


@Component

public 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。我应该如何将模拟对象添加到源列表中,或者您能告诉我是否有更好的方法吗?


白衣非少年
浏览 112回答 3
3回答

不负相思意

如前所述,不要尝试模拟该List对象。通常也避免为您可以简单地自己创建的对象创建模拟,并尝试将自己限制为仅模拟依赖项。测试的简化版本可能如下所示:由于您的测试涵盖的内容比Unit BookService 我决定在这个例子中将其最小化。您可能希望在针对特定实现的测试中执行所有其他操作。@Testpublic void getBooksByCategory() {&nbsp; &nbsp; List<Book> empikBestsellers = EmpikBookProvider.prepare5Bestsellers();&nbsp; &nbsp; List<Book> merlinBestsellers = MerlinBookProvider.prepare5Bestsellers();&nbsp; &nbsp; BookServiceSource bookServiceSource1 = Mockito.mock(BookServiceSource.class);&nbsp; &nbsp; Mockito.when(bookServiceSource1.getName()).thenReturn(Bookstore.EMPIK);&nbsp; &nbsp; Mockito.when(bookServiceSource1.getBooksByCategory(CategoryType.CRIME)).thenReturn(empikBestsellers);&nbsp; &nbsp;&nbsp; &nbsp; BookServiceSource bookServiceSource2 = Mockito.mock(BookServiceSource.class);&nbsp; &nbsp; Mockito.when(bookServiceSource2.getName()).thenReturn(Bookstore.MERLIN);&nbsp; &nbsp; Mockito.when(bookServiceSource2.getBooksByCategory(CategoryType.CRIME)).thenReturn(merlinBestsellers);&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; List<BookServiceSource> sources = new ArrayList<>();&nbsp; &nbsp; sources.add(bookServiceSource1);&nbsp; &nbsp; sources.add(bookServiceSource2);&nbsp; &nbsp; BookService service = new BookService(sources);&nbsp; &nbsp; Map<Bookstore, List<Book>> actualMap = service.getBooksByCategory(CategoryType.CRIME);&nbsp; &nbsp; // compare result}

繁花如伊

我认为您不应该嘲笑 BookServiceSource 列表,因为您添加的内容不会执行任何操作,因为它不是真正的列表。如果可以的话,不应该使用它,它有静默失败的倾向。我试图提出的另一点是您正在使用模拟列表,因此当它被告知添加元素时它不会。您可以使用两种解决问题的方法。首先,您可以为 BookServiceSources 流创建 when thenreturn,而不是推荐的解决方案。其次,更好的方法是创建一个使用 @Before 注释创建 BookService 的 testSetup 方法。@Beforepublic void testSetup(){ List<BookServiceSource> list = new LinkedList<>(); list.add(merlinSource); list.add(empikSource); bookService = new BookService(list);}

鸿蒙传说

尝试@Spy。它允许您注入您自己初始化的列表的实际实例,也可以部分模拟。@Spy private List<BookServiceSource> sources = new ArrayList<>();似乎您为列表使用了不同的名称,更喜欢使用注入模拟字段的 smae 名称;消息来源。这里有很好的解释。5. Mockito 中的模拟与间谍:当 Mockito 创建一个模拟时——它是从一个类型的类中创建的,而不是从一个实际的实例中创建的。模拟只是创建了类的一个基本的 shell 实例,完全用于跟踪与它的交互。另一方面,间谍将包装现有实例。它仍将以与普通实例相同的方式运行——唯一的区别是它还将被检测以跟踪与其进行的所有交互。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java