Mockito调用了已存根的方法,即使使用了doReturn

huangapple go评论81阅读模式
英文:

Mockito calls stubbed method even if using doReturn

问题

这是我的服务类,其中包含我想要进行存根化的方法调用。

public class ProjectService implements SomeInterfance {

// 第三方服务
private final DamConnector damConnector;
// 其他字段

    public ProjectDTO save(ProjectDTO projectDTO) {
		log.debug("Request to save Project : {}", projectDTO);
		// 一些操作
		synchronizeWithDamAndSave(project, parentChanging); // 这是我想要跳过的方法调用
		// 其他操作
		return projectMapper.toDto(project, this);
	}

    // 我想要存根化的方法
    public Asset synchronizeWithDamAndSave(Project project, boolean includeDocuments) {
	    Asset asset = synchronizeWithDam(project, includeDocuments);
	    projectRepository.save(project);
	    return asset;
    }

}

还有我的集成测试类:

@SpringBootTest(classes = SppApp.class)
public class ProjectResourceIT {

// 其他字段

// 由于我的服务需要进行服务调用,所以我使用了自动装配
@Autowired
private ProjectService projectService;

// 这是我的设置方法,在这里我创建了项目服务的 spy,并在调用我的方法时定义了 doReturn 的行为
@BeforeEach
public void setup() {
	ProjectService spyProjectService = Mockito.spy(projectService);
	Mockito.doReturn(new Asset()).when(spyProjectService).synchronizeWithDamAndSave(Mockito.any(Project.class), Mockito.anyBoolean());
	MockitoAnnotations.initMocks(this);

	final ProjectResource projectResource = new ProjectResource(spyProjectService, clientService, securityService);
	this.restProjectMockMvc = MockMvcBuilders.standaloneSetup(projectResource)
		.setCustomArgumentResolvers(pageableArgumentResolver)
		.setControllerAdvice(exceptionTranslator)
		.setConversionService(createFormattingConversionService())
		.setMessageConverters(jacksonMessageConverter)
		.setValidator(validator).build();
	}

}
...

public void updateProject() throws Exception {
    // 测试的初始化

    // 这是我调用控制器的地方
	restProjectMockMvc.perform(put("/api/projects")
		.contentType(TestUtil.APPLICATION_JSON_UTF8)
		.content(TestUtil.convertObjectToJsonBytes(projectDTO)))
		.andExpect(status().isOk());
	}

}

在我这种情况下的问题是,Mockito 在调用以下行之后就进入了 synchronizeWithDamAndSave 方法:

Mockito.doReturn(new Asset()).when(spyProjectService).synchronizeWithDamAndSave(Mockito.any(Project.class), Mockito.anyBoolean());

这一行在方法从 REST API 调用之前被调用。关于为什么会发生这种情况,您应该怎么做,或者出现问题的可能原因,您有什么提示吗?

英文:

I want to create an integration test where a put method is called on a controller and it updates a certain object. During this process, a service class is involved which calls a third party API to do some stuff. In my case, I want to stub the service method which is involved in calling the third party as it is not the point to test the third party.

Having that said, I will present my code and I wait for an answer about why this does not work as expected and/or any other workaround.

This is my service class in which is the method call I want to stub.

public class ProjectService implements SomeInterfance {

// the third party service
private final DamConnector damConnector;
// some other fields

    public ProjectDTO save(ProjectDTO projectDTO) {
		log.debug("Request to save Project : {}", projectDTO);
		// some operations
		synchronizeWithDamAndSave(project, parentChanging); //this is the method call I want to be skiped
		//other operations
		return projectMapper.toDto(project, this);
	}

    //the method that I want to stub
    public Asset synchronizeWithDamAndSave(Project project, boolean includeDocuments) {
	    Asset asset = synchronizeWithDam(project, includeDocuments);
	    projectRepository.save(project);
	    return asset;
    }

}

And my integration test class:

@SpringBootTest(classes = SppApp.class)
public class ProjectResourceIT {

//other fields

//my service use autowire as it needs to make the service calls
@Autowired
private ProjectService projectService;

//this is my setup method where I create the spy of project service and define the doReturn behavior when my method is called
@BeforeEach
public void setup() {
	ProjectService spyProjectService = Mockito.spy(projectService);
	Mockito.doReturn(new Asset()).when(spyProjectService).synchronizeWithDamAndSave(Mockito.any(Project.class),Mockito.anyBoolean());
	MockitoAnnotations.initMocks(this);


	final ProjectResource projectResource = new ProjectResource(spyProjectService, clientService, securityService);
	this.restProjectMockMvc = MockMvcBuilders.standaloneSetup(projectResource)
		.setCustomArgumentResolvers(pageableArgumentResolver)
		.setControllerAdvice(exceptionTranslator)
		.setConversionService(createFormattingConversionService())
		.setMessageConverters(jacksonMessageConverter)
		.setValidator(validator).build();
	}

}
...

public void updateProject() throws Exception {
    // initialization of the test

    // this is where I call my controller
	restProjectMockMvc.perform(put("/api/projects")
		.contentType(TestUtil.APPLICATION_JSON_UTF8)
		.content(TestUtil.convertObjectToJsonBytes(projectDTO)))
		.andExpect(status().isOk());
	}

}

The problem in my case is that mockito enters in synchronizeWithDamAndSave method just after

Mockito.doReturn(new Asset()).when(spyProjectService).synchronizeWithDamAndSave(Mockito.any(Project.class),Mockito.anyBoolean());

this line is called, before the method to be called from the rest api.

What should I do? Any hints about why this is happening?

答案1

得分: 1

Spring Boot的代理在与Mockito一起使用时无法正常工作。请使用@SpyBean替代@Autowired。

英文:

Spring Boot's proxies are not working wit Mockito. Use @SpyBean instead of @Autowired.

huangapple
  • 本文由 发表于 2020年10月19日 20:15:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/64427146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定