【问题标题】:How to get result from not mocked method?如何从非模拟方法中获取结果?
【发布时间】:2018-01-30 19:10:57
【问题描述】:

我在从未模拟的方法中获取结果时遇到问题。我不想模拟结果,而是想从这种方法中获得真正的结果。该方法在应用程序中有效,所以这不是问题。我有一个测试:

    @Test
public void shouldGetCompaniesToSelect() throws Exception {
    Company company = new Company("company", new Address());
    Company relatedCompany1 = new Company("relatedCompanyName1", new Address());
    Company notRelatedCompany = new Company("notRelatedCompanyName", new Address());
    Company relatedCompany2 = new Company("relatedCompanyName2", new Address());
    CompanyRelation companyRelation1 = new CompanyRelation(relatedCompany1);
    CompanyRelation companyRelation2 = new CompanyRelation(relatedCompany2);
    company.getCompanyRelations().add(companyRelation1);
    company.getCompanyRelations().add(companyRelation2);

    when(companyServiceMock.findAll()).thenReturn(Arrays.asList
            (company, relatedCompany1, notRelatedCompany, relatedCompany2));
    when(companyServiceMock.findOne(1L)).thenReturn(company);

    List<Company> companiesToSelect =  companyServiceMock.findCompaniesToSelect(company);

    mockMvc.perform(get("/company/1"))
            .andExpect(model().attribute("companiesToSelect", hasSize(1)))
            .andExpect(model().attribute("companiesToSelect", hasItem(
                    hasProperty("relatedCompany", hasProperty(
                            "name", is("notRelatedCompanyName")
                    )))));
}

有 2 个模拟方法(findAll 和 findOne),然后我想执行方法并从 findCompaniesToSelect(公司 - 这是为测试创建的对象)中获得真实结果。 companyToSelect 的大小应该是 1,但它返回 0。

findCompaniesToSelect 方法:

public List<Company> findCompaniesToSelect(Company company) {
    List<Company> companiesToSelect = companyRepository.findAll();
    for (CompanyRelation companyRelation :
            company.getCompanyRelations()) {
        companiesToSelect.remove(companyRelation.getRelatedCompany());
    }
    companiesToSelect.remove(company);
    return companiesToSelect;
}

我该怎么做?

编辑 1:

好的,所以我把它改成@Spy,把存根改成:

    Mockito.doReturn(Arrays.asList(company, relatedCompany1, 
    notRelatedCompany, relatedCompany2)).when(companyServiceMock).findAll();
    Mockito.doReturn(company).when(companyServiceMock).findOne(1L);

但是当我运行测试时,findCompaniesToSelect() 方法使用的是真实公司而不是模拟公司。

好的,所以现在的问题是当调用 findCompaniesToSelect() 方法时,调用的是 companyRepository.findAll 方法。我想从测试中调用模拟的 findAll 方法来获取模拟的公司而不是真实的公司。

编辑 2:

好的,问题是因为 findCompaniesToSelect() 方法使用存储库,而不是服务。 :D

【问题讨论】:

    标签: java spring testing mocking mockito


    【解决方案1】:

    如果您想在一个对象上同时使用模拟方法和真实方法调用,那么您需要使用间谍而不是模拟。

    @Spy
    CompanyService companyServiceSpy
    

    不过,您需要以不同的方式存根模拟方法。使用 doReturn(...).when(...) 而不是您当前使用的存根。

    查看http://www.baeldung.com/mockito-spy 了解有关使用间谍的更多信息。

    编辑:由于您在测试中模拟某些行为,您应该为您的 MockMvc 对象使用独立设置并将模拟注入您的控制器,如下所示:

    MockMvc mockMvc;
    
    @Spy
    CompanyService companyServiceSpy;
    
    @InjectMocks
    CompanyController companyController;
    
    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(companyController).build();
    }
    

    编辑 2: 您也可以通过在当前设置中将 @Spy 更改为 @SpyBean 来解决此问题。对此不是 100% 确定,因为我不完全熟悉 Spring Boot 如何设置测试。

    【讨论】:

    • 我添加了新帖子
    • 那么 CompanyService 是一个@Controller??
    • 不。 CompanyController 正在使用带有方法 findCompaniesToSelect() 的 CompanyService。
    • 它是 Autowired,SpringBoot。
    • 我不太熟悉 Spring boot 如何为您设置 mockMvc 对象。但它应该是一个独立的设置,您可以在其中引用使用 @InjectMocks 注释装饰的 Controller 类。可能不值得使用 Spring Boot 提供的那个。
    【解决方案2】:

    发生这种情况是因为您的服务类(即 companyService)被模拟了。 我应该建议使用 Restasured 来测试您的 Restservice,它不需要为您的 RestService 组件的不同方法创建模拟,即您不需要模拟 CompanyService。

    进一步阅读:

    RestAssured

    Example Code for RestAssured testing

    【讨论】:

      猜你喜欢
      • 2012-07-29
      • 1970-01-01
      • 2016-07-13
      • 2014-04-07
      • 2021-06-04
      • 2017-06-05
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多