mocking bean 并不总是有效
Posted
技术标签:
【中文标题】mocking bean 并不总是有效【英文标题】:mocking bean not always works 【发布时间】:2018-07-17 20:44:13 【问题描述】:我在 junit 测试中遇到了一个奇怪的行为。 对于某些测试,我需要模拟一个微服务客户端 bean。 我使用 BDDMockito.given 来模拟微服务响应。 当我在 IntelliJ 测试中运行“所有测试”时使用它失败,因为客户端尝试从微服务加载。 当我重新运行那些失败的测试时,它就可以工作了。
我尝试启动自定义选择的测试,但找不到另一个导致这些测试失败的测试。
这可能是产生这种行为的测试数(500+)吗?
@MockBean
protected FileserverClient fileserverClient;
@Before
public void initMockBeans()
given(fileserverClient.createFrom64(any(File64.class)))
.willReturn(FileCreatorForTest.createFile());
编辑
这里的错误: 它正在尝试连接到我的领事以获取通往我的微服务的路线。不必这样做,因为 FeignClient 应该已经被模拟了。
2018-02-07 14:52:58.325 WARN 22665 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'retryableRibbonLoadBalancingHttpClient' defined in org.springframework.cloud.netflix.ribbon.apache.HttpClientRibbonConfiguration: Unsatisfied dependency expressed through method 'retryableRibbonLoadBalancingHttpClient' parameter 2; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ribbonLoadBalancer' defined in org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.netflix.loadbalancer.ILoadBalancer]: Factory method 'ribbonLoadBalancer' threw exception; nested exception is com.ecwid.consul.transport.TransportException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1] failed: Connexion refusée (Connection refused)
2018-02-07 14:52:58.333 ERROR 22665 --- [ main] o.z.p.spring.web.advice.AdviceTrait : Internal Server Error
我尝试启动除一个之外的所有测试文件,它可以工作。我选择排除的一个并禁用另一个它可以工作(我玩这个游戏很长时间试图找到一个可能导致这种情况的测试文件)。
潜在失败测试的示例代码:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MeetingApp.class,SecurityBeanOverrideConfiguration.class)
public class MeetingRoomResourceIntTest extends BaseResourceTest
@Before
public void setup()
MockitoAnnotations.initMocks(this);
final MeetingRoomResource meetingRoomResource = new MeetingRoomResource(meetingRoomService, meetingRoomQueryService);
this.restMeetingRoomMockMvc = MockMvcBuilders.standaloneSetup(meetingRoomResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService())
.setMessageConverters(jacksonMessageConverter).build();
@Test
@Transactional
public void createMeetingRoom() throws Exception
int databaseSizeBeforeCreate = meetingRoomRepository.findAll().size();
// Create the MeetingRoom
MeetingRoomDTO meetingRoomDTO = meetingRoomMapper.toDto(meetingRoom);
meetingRoomDTO.setFile64(FileCreatorForTest.createFile64());
restMeetingRoomMockMvc.perform(post("/api/meeting-rooms")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(meetingRoomDTO)))
.andExpect(status().isCreated());
// Validate the MeetingRoom in the database
List<MeetingRoom> meetingRoomList = meetingRoomRepository.findAll();
assertThat(meetingRoomList).hasSize(databaseSizeBeforeCreate + 1);
MeetingRoom testMeetingRoom = meetingRoomList.get(meetingRoomList.size() - 1);
assertThat(testMeetingRoom.getMdLocationId()).isEqualTo(DEFAULT_MD_LOCATION_ID);
assertThat(testMeetingRoom.getFspictureId()).isEqualTo(FileCreatorForTest.DEFAULT_FS_PICTURE_ID.intValue());
assertThat(testMeetingRoom.getName()).isEqualTo(DEFAULT_NAME);
assertThat(testMeetingRoom.getDescription()).isEqualTo(DEFAULT_DESCRIPTION);
assertThat(testMeetingRoom.getCapacity()).isEqualTo(DEFAULT_CAPACITY);
assertThat(testMeetingRoom.isNaturalDayLight()).isEqualTo(DEFAULT_NATURAL_DAY_LIGHT);
assertThat(testMeetingRoom.isPamFriendly()).isEqualTo(DEFAULT_PAM_FRIENDLY);
assertThat(testMeetingRoom.getStars()).isEqualTo(DEFAULT_STARS);
assertThat(testMeetingRoom.getWrapUpTime()).isEqualTo(DEFAULT_WRAP_UP_TIME);
还有我的 BaseResourceTest:
public abstract class BaseResourceTest
@MockBean
protected FileserverClient fileserverClient;
public BaseResourceTest()
MyCurrentTenantIdentifierResolver.forceTenantId("junit");
@Before
public void initMockBeans()
given(fileserverClient.createFrom64(any(File64.class)))
.willReturn(FileCreatorForTest.createFile());
编辑 2
客户端在 EntityListener 组件中使用并静态设置。这会导致不稳定吗?
@Component
public class FileServerDependantListener
private Logger logger;
static private FileserverClient fileserverClient;
private AbstractFileServerDependantEntity entity;
public FileServerDependantListener()
logger = Logger.getLogger(FileServerDependantListener.class.getName());
@Autowired
public void init(FileserverClient fileserverClient)
FileServerDependantListener.fileserverClient = fileserverClient;
@PreUpdate
@PrePersist
public void preCommit(AbstractFileServerDependantEntity entity)
if (entity.getFile64() != null)
entity.getFile64().setFileType(entity.getFileType());
File file = fileserverClient.createFrom64(entity.getFile64());
entity.setFsPictureId(file.getId());
【问题讨论】:
您遇到什么错误?您还可以使用类注释发布您的测试类的代码吗? 【参考方案1】:在 IntelliJ 中一起运行测试时,测试的应用程序上下文可能会在测试之间共享。如果部分上下文受到测试本身甚至上下文加载的影响,这可能会导致问题。
您可以尝试使用 @DirtiesContext
注释所有测试类,以确保为每个测试类加载新的应用程序上下文。如果需要,此注解也可以在 @Test
方法的方法级别使用。
【讨论】:
它可以工作,但会减慢测试速度。我将使用它来隔离那些“污染”上下文的测试。以上是关于mocking bean 并不总是有效的主要内容,如果未能解决你的问题,请参考以下文章