可重试注解-Junit 5- Mockito -是否可能

hfyxw5xn  于 2023-02-08  发布在  其他
关注(0)|答案(2)|浏览(143)

是否可以使用Junit5mockito为可重试的注解编写单元测试?
我有一个只有一个方法的服务接口,该方法从远程url下载文件

@service
interface downloadpdf{
@Retryable(value = { FileNotFoundException.class, HttpClientErrorException.class }, maxAttempts = 5, backoff = @Backoff(delay = 1000))
public string downloadpdffile(string remoteurl, string pdfname);    
}

我试过引用站点,发现使用Spring4JunitRunner实现来测试重试。对实现感到困惑。是否可以使用Junit 5 mockito为可重试的注解编写单元测试?您能否在此处详细说明解决方案?

yx2lnoni

yx2lnoni1#

您需要使用@SpringJUnitConfig(相当于JUnit4 runner),或者使用启动时使用@SpringBootTest
@Retryable只适用于Spring管理的bean--它将bean Package 在代理中。

@SpringBootApplication
@EnableRetry
public class So71849077Application {

    public static void main(String[] args) {
        SpringApplication.run(So71849077Application.class, args);
    }

}

@Component
class RetryableClass {

    private SomeService service;

    void setService(SomeService service) {
        this.service = service;
    }

    @Retryable
    void retryableMethod(String in) {
        service.callme();
        throw new RuntimeException();
    }

    @Recover
    void recover(Exception ex, String  in) {
        service.failed();
    }

}

interface SomeService {

    void callme();

    void failed();

}
@SpringBootTest
class So71849077ApplicationTests {

    @MockBean
    SomeService service;

    @Test
    void testRetry(@Autowired RetryableClass retryable) {
        SomeService service = mock(SomeService.class);
        retryable.setService(service);

        retryable.retryableMethod("foo");
        verify(service, times(3)).callme();
        verify(service).failed();
    }

}
eni9jsuy

eni9jsuy2#

我也尝试过使用Junit5来实现这一点。
尝试了各种选项,但没有帮助。然后在谷歌上搜索了几个小时后,得到了以下链接,它帮助成功。
https://doctorjw.wordpress.com/2022/04/29/spring-testing-a-single-bean-in-junit-5-springextension/
参考代码如下,详细解释请参考博客.

@Component
public class MyClass {
private ObjectMapper objectMapper;

private RestTemplate restTemplate;

@Value("${testValue:5}")
private int value;

@Retryable(....)
public void doStuff() throws SomeException {
...
}
}

我发现,如果我这样声明测试类:

@ExtendWith( SpringExtension.class )
@Import( { MyClass.class, ObjectMapper.class } )
@EnableRetry
public class MyClassTest {

@Autowired
private MyClass myClass;

@MockBean
private RestTemplate restTemplate;

@Autowired
private ObjectMapper objectMapper;

@BeforeEach
public void setup() {
    // If we are going to jack with the object configuration,
    // we need to do so on the actual object, not the Spring proxy.
    // So, use AopTestUtils to get around the proxy to the actual obj.

    TestingUtils.setFieldValue( AopTestUtils.getTargetObject( myClass ), "value", 10 );
}

}

您会注意到其中包含了另外一个类TestingUtils.class。

public class TestingUtils {

public static void setFieldValue( Object object, String fieldName, Object value ) {
    Field field = ReflectionUtils.findField( object.getClass(), fieldName );
    ReflectionUtils.makeAccessible( field );

    ReflectionUtils.setField( field, object, value );
}
}

所有的学分归博客的作者。

相关问题