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 并不总是有效的主要内容,如果未能解决你的问题,请参考以下文章

条件变量并不总是有效

removeFromSuperview() 并不总是有效

为啥 constexpr 隐式转换并不总是有效?

Click() 方法并不总是有效

IE、XDomainRequest 并不总是有效

为啥 JavaScript Intellisense 在 Visual Studio 2012 中并不总是有效?