java - 如何使用 PowerMockito 模拟局部变量?

标签 java unit-testing mockito powermockito

当其他类调用方法“ProductAdapterService.adapt”时,我想模拟“source”。

如何处理?我确实尝试了很多方法。请帮我。我是新人。非常感谢!

    public class ProductAdapterService {
private final SearchParameter parameter;
private List<Festival> festivals;

public ProductAdapterService(SearchParameter parameter) {
    this.parameter = parameter;
}

public SingleProduct adapt(SearchHit hit, boolean bidding) {

    //I want to mock "source", I don't want to use "hit.getSource()"
    Map<String, Object> source = hit.getSource();

    SingleProduct sp = new SingleProduct();
    sp.setId(TypeConverter.toInt(source.get(FieldName.PRODUCT_ID)));
    sp.setName(TypeConverter.toString(source.get(FieldName.NAME)));
    sp.setPrice(this.price(source.get(FieldName.PRICE), source.get(FieldName.PRICE_MAP), source.get(FieldName.FIRST_START_CITIES)));
    sp.setLevel(TypeConverter.toInt(source.get(FieldName.PRODUCT_LEVEL)));
    sp.setDepartureCityId(this.departureCity(source.get(FieldName.DEPARTURE_CITY_ID), source.get(FieldName.FIRST_START_CITIES)));
    sp.setSaleMode(TypeConverter.toString(source.get(FieldName.SALE_MODE)));
    sp.setBrandName(this.providerBrandName(source.get(FieldName.PROVIDER_BRAND)));
    sp.setSaleCount(TypeConverter.toInt(source.get(FieldName.MONTHLY_ORDER)));
    sp.setCommentCount(TypeConverter.toInt(source.get(FieldName.COMMENT_COUNT)));
    sp.setCommentScore(TypeConverter.toFloat(source.get(FieldName.COMMENT_SCORE)));
    sp.setBuType(BuType.GT);
    sp.setType(this.productType(source.get(FieldName.SEARCH_TAB_TYPE_SHOW), sp.getSaleMode()));
    sp.setSaleout(this.saleout(source.get(FieldName.NON_SALEOUT_CITIES), sp.getDepartureCityId()));
    if (!sp.isSaleout()) {
        sp.setFestival(this.festival(source.get(FieldName.FESTIVAL_IDS)));
    }
    System.out.println("sp.getName(): " + sp.getName());
    return sp;
}}

下面是我的测试代码:

public class TabSearcherTest0 {

@Test
public void test() {
    SearchParameter parameter = SearchParameter.create();
    Ghost.begin();
    parameter.getFiltered().setTab(TabType.ALL);
    parameter.getPoi().setKeyword("Spa");
    parameter.getClient().setTrace(TraceMode.MAIN);

    Map<String, Object> mapMock = new HashMap<String, Object>();
    mapMock.put("productgroupid", "12877");
    mapMock.put("productid", "5539739");
    mapMock.put("firststartcitys", "[1, 2]");
    mapMock.put("nonsaleoutcities", "[1, 2]");
    mapMock.put("productdiamondlevel", "4");
    mapMock.put("commentcount", "0");
    mapMock.put("price", "0.0");
    mapMock.put("name", "TestName");
    mapMock.put("searchtabtypeshow", "1");
    mapMock.put("comment", "0.0");
    mapMock.put("salemode", "S");
    mapMock.put("providerbrandid", "999999");
    mapMock.put("departurecityid", "2");

    // how to inject the map?
    // ???

    SearchModel model = SearchContext.createContext(parameter).search();
    Ghost.end();
    System.out.println(model);

}}

最佳答案

你“ mock ”的方式是错误的。 当您无法使用真正的类实现时才使用它;但您需要控制某些对象如何对其方法调用使用react。

您的测试方法如下所示:

public SingleProduct adapt(SearchHit hit, boolean bidding) {
  //I want to mock "source", I don't want to use "hit.getSource()"
  Map<String, Object> source = hit.getSource();

错误:您想要确保使用hit.getSource()。因为您的生产代码正在使用的是;然后您将单元测试写入该代码的文本中。所以你希望你的生产代码做它“正常”的事情。

因此,非常简单的解决方案是:

 @Test
 public void testAdapt() {
   SearchHit mockedHit = mock(SearchHit.class);

   Map<String, Object> resonseForGetSource = new HashMap<>();
   resonseForGetSource.put("productgroupid", "12877"); 
   ...

   doReturn(resonseForGetSource).when(mockedHit.getSource());

   ProductAdapterService underTest = ...
   underTest.adapt(mockedHit, true);
   ... probably some asserts

或者类似的东西(不要在 doReturn/when 详细信息上钉我)

您可以在这里看到:您的生产代码需要该映射来完成其工作;因此,您只需确保这样的 map 对象出现在您的生产代码中即可。

如果可以使用真实 SearchHit 对象(您可以使用这样的 map 进行配置);那么使用它甚至比模拟该对象更好。

您绝对会尝试最小化您对模拟的使用。您仅使用它来控制特定测试期间使用的对象。

除此之外:您不清楚单元测试的范围。为了测试该方法,您不需要任何幽灵。您显示的单元测试代码在您在这里向我们展示的类的上下文中根本没有意义!因此:你最好退后一步,仔细研究“我有哪些单元”和“如何对单元 X 进行精确的单元测试”。您不会通过测试“Y”来发短信“X”!

关于java - 如何使用 PowerMockito 模拟局部变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42361228/

相关文章:

java - 在 Eclipse 中将静态方法重构为实例方法

java - JUnit 测试期间如何在 Spring 中使用不同的 MongoDB 数据库

java - @TestSubject 和@InjectMocks 之间的区别?

c# - 使用属性 CharacterSet 的值模拟 HttpWebResponse

java - 检查 EasyMock 上是否调用了方法

r - 在二进制 R 包中包含测试

java - jMonkeyEngine:flyCam 和 inputManager 都返回 NULL

mockito thenReturn 中的 Java 枚举列表

java - 对泛型类使用 Matchers.isNull()

Spring - 禁用特定 Bean 的 Autoproxy