`Mockito.doThrow()`没有抛出任何异常。

huangapple 未分类评论76阅读模式
英文:

Mockito.doThrow() not throwing any exception

问题

以下是翻译后的内容:

Service:

@Component
public class FileHandler {

    private static final Logger log = LoggerFactory.getLogger(FileHandler.class);

    private final SSHAccess sshAccess;
    @Value("${datastore.location}")
    private String dataStoreDir;

    public FileHandler(SSHAccess sshAccess){
        this.sshAccess = sshAccess;
    }

    public Either<Pair<Exception, FileRecord>, FileRecord> transferFile(FileRecord fileRecord){
        try {
            var sourceURI = new URI(fileRecord.getSourceURI());
            var digest = sshAccess.execute("md5sum " + sourceURI.getPath())
                    .replaceFirst("([^\\s]+)[\\d\\D]*", "$1");
            if (digest.equals(fileRecord.getSourceDigest())) {
                log.info(Thread.currentThread().getName() + ": Copying file: " + fileRecord.getId() + " of submission: " + fileRecord.getOwnedBy());
                sshAccess.download(sourceURI.getPath(), new File(mkdir(dataStoreDir, digest), digest));
                log.info(Thread.currentThread().getName() + ": Copying of file: " + fileRecord.getId() + " of submission: " + fileRecord.getOwnedBy() + " finished.");
                return Either.Right(fileRecord);
            } else {
                log.error("MD5 mismatch for source file {}", sourceURI.getPath());
                return Either.Left(Pair.of(new FileHandlerException("MD5 mismatch"), fileRecord));
            }

        } catch (URISyntaxException
                | IOException
                e) {
            return Either.Left(Pair.of(new FileHandlerException(e), fileRecord));
        }
    }

    private File mkdir(String dataStoreDir, String digest) throws IOException {
        File dir = new File(dataStoreDir, digest.substring(0, 3));
        if (!dir.exists() && !dir.mkdirs()) {
            log.error("Unable to create directory {}", dir);
            throw new IOException("Unable to create directory " + dir);
        }
        return dir;
    }
}

Test Class:

@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class FileHandlerTest {
    private FileHandler fileHandler;

    @Mock
    private SSHAccess sshAccess;

    @BeforeAll
    public void init(){
       fileHandler = Mockito.spy(new FileHandler(sshAccess));
    }

    @Test
    public void transferFileShouldReturnFileHandlerExceptionOnEitherLeftWhenSSHclientThrowsIOException() throws IOException {
        FileRecord fileRecord = getFileRecord();
        var digest = "6e484ac23110fae10021e";
        when(sshAccess.execute(anyString())).thenReturn(digest);
        doThrow(IOException.class).when(sshAccess).download(anyString(), any(File.class));
        var result = fileHandler.transferFile(fileRecord);
        Assertions.assertTrue(result.getLeft().isPresent()
                && result.getLeft().get().getFirst() instanceof FileHandlerException);
    }

    private FileRecord getFileRecord() {
        var fileRecord = new FileRecord();
        fileRecord.setId(1L);
        fileRecord.setOwnedBy(1000);
        fileRecord.setSourceURI("scp:host/test/uri/filename");
        fileRecord.setSourceDigest("6e484ac23110fae10021e");
        return fileRecord;
    }
}

但是当我运行这个测试用例时,doThrow() 并没有抛出任何异常。方法在没有异常的情况下执行,并且测试失败。我不确定我在这里做错了什么。请帮忙解决。

英文:

I am trying to stub a void method of a mocked object to return an exception. This mocked object passed as dependency to the service which I am writing tests for.

Service:

@Component
public class FileHandler {

    private static final Logger log = LoggerFactory.getLogger(FileHandler.class);

    private final SSHAccess sshAccess;
    @Value(&quot;${datastore.location}&quot;)
    private String dataStoreDir;

    public FileHandler(SSHAccess sshAccess){
        this.sshAccess = sshAccess;
    }

    public Either&lt;Pair&lt;Exception, FileRecord&gt;, FileRecord&gt; transferFile(FileRecord fileRecord){
        try {
            var sourceURI = new URI(fileRecord.getSourceURI());
            var digest = sshAccess.execute(&quot;md5sum &quot; + sourceURI.getPath())
                    .replaceFirst(&quot;([^\\s]+)[\\d\\D]*&quot;, &quot;$1&quot;);
            if (digest.equals(fileRecord.getSourceDigest())) {
                log.info(Thread.currentThread().getName() + &quot;: Copying file: &quot; + fileRecord.getId() + &quot; of submission: &quot; + fileRecord.getOwnedBy());
                sshAccess.download(sourceURI.getPath(),new File(mkdir(dataStoreDir, digest), digest));
                log.info(Thread.currentThread().getName() + &quot;: Copying of file: &quot; + fileRecord.getId() + &quot; of submission: &quot; + fileRecord.getOwnedBy() + &quot; finished.&quot;);
                return Either.Right(fileRecord);
            }else{
                log.error(&quot;MD5 mismatch for source file {}&quot;, sourceURI.getPath());
                return Either.Left(Pair.of(new FileHandlerException(&quot;MD5 mismatch&quot;), fileRecord));
            }

        } catch (URISyntaxException
                | IOException
                e) {
            return Either.Left(Pair.of(new FileHandlerException(e), fileRecord));
        }
    }

    private File mkdir(String dataStoreDir, String digest) throws IOException {
        File dir = new File(dataStoreDir, digest.substring(0, 3));
            if (!dir.exists() &amp;&amp; !dir.mkdirs()) {
                log.error(&quot;Unable to create directory {}&quot;, dir);
                throw new IOException(&quot;Unable to create directory &quot; + dir);
            }
        return dir;
    }
}

Test Class:

@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class FileHandlerTest {
    private FileHandler fileHandler;

    @Mock
    private SSHAccess sshAccess;

    @BeforeAll
    public void init(){
       fileHandler = Mockito.spy(new FileHandler(sshAccess));
     
    }

        
    @Test
    public void transferFileShouldReturnFileHandlerExceptionOnEitherLeftWhenSSHclientThrowsIOException() throws IOException {
        FileRecord fileRecord = getFileRecord();
        var digest = &quot;6e484ac23110fae10021e&quot;;
        when(sshAccess.execute(anyString())).thenReturn(digest);
        doThrow(IOException.class).when(sshAccess).download(anyString(), any(File.class));
        var result = fileHandler.transferFile(fileRecord);
        Assertions.assertTrue(result.getLeft().isPresent()
                &amp;&amp; result.getLeft().get().getFirst() instanceof FileHandlerException);
    }

    private FileRecord getFileRecord() {
        var fileRecord = new FileRecord();
        fileRecord.setId(1L);
        fileRecord.setOwnedBy(1000);
        fileRecord.setSourceURI(&quot;scp:host/test/uri/filename&quot;);
        fileRecord.setSourceDigest(&quot;6e484ac23110fae10021e&quot;);
        return fileRecord;
    }
}

But when I run this test case, doThrow() doesn't throw any exception. Method executed without any exception and test failed. I am not sure what I am doing wrong here. Please help.

答案1

得分: 0

不确定为什么要使用 @SpringBootTest 注解,它会尝试创建一个类似于运行应用程序时的上下文。所以在这种情况下,您可以停止实例化 FileHandler,并且只需对其进行模拟,以及对 SSHAccess bean 进行模拟,或者使用 @MockBean 替代 @Mock

基本上,您应该有类似于这样的代码:

@SpyBean
private FileHandler fileHandler;

@MockBean
private SSHAccess sshAccess;
英文:

Not sure why are you using the @SpringBootTest annotation which will try to raise a similar context with the one when you are running the app. So in this case you could stop instantiating your FileHandler and just spy on it and on your SSHAccess beans or use @MockBean instead of @Mock.

Basically you should have something like this

@SpyBean
private FileHandler fileHandler;

@MockBean
private SSHAccess sshAccess;

答案2

得分: 0

你正在使用 Junit 5。对于 Junit 5,你不需要使用方法 @SpringBootTest,而需要使用 @ExtendWith(MockitoExtension.class)

@ExtendWith(MockitoExtension.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class FileHandlerTest {
    private FileHandler fileHandler;

    @Mock
    private SSHAccess sshAccess;

    @BeforeAll
    public void init(){
       fileHandler = Mockito.mock(new FileHandler(sshAccess));
     
    }
    // ...
    // ...
    // ...
}

另外,代替 Mockito.spy(new FileHandler(sshAccess)),你可以尝试使用 Mockito.mock(new FileHandler(sshAccess))

英文:

You are using Junit 5. For Junit 5 you don't need the method @SpringBootTest, you need to use @ExtendWith(MockitoExtension.class)

@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class FileHandlerTest {
    private FileHandler fileHandler;

    @Mock
    private SSHAccess sshAccess;

    @BeforeAll
    public void init(){
       fileHandler = Mockito.spy(new FileHandler(sshAccess));
     
    }
.....
.....
.....
}

Also instead of Mockito.spy(new FileHandler(sshAccess)) you can try Mockito.mock(new FileHandler(sshAccess))

huangapple
  • 本文由 发表于 2020年8月14日 23:23:28
  • 转载请务必保留本文链接:https://java.coder-hub.com/63415635.html
匿名

发表评论

匿名网友

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

确定