当前位置: 首页 > 知识库问答 >
问题:

如何模拟'std::fs::File',以便检查'File::set_len'是否在单元测试中正确使用?

汝宏伯
2023-03-14

当我检查<code>File::set_len(..)时,它看起来像是为<code>结构文件

目标:测试 foo 将文件打开为读/写,执行以下操作:读取,写入,查找和修剪文件到一定大小。我们希望在测试中提供文件的初始状态,并检查结果。最好在内存中。

如何测试依赖于< code>set_len的代码?(< code>io::Seek或其他特征至今没有帮助)。

我想嘲笑它。

让我们举一个玩具例子,让讨论更容易:

#![allow(unused_variables)]

use std::error::Error;
use std::fs::File;
use std::io::Cursor;

// assumes that file is open in Read/Write mode
// foo performs reads and writes and Seeks
// at the end wants to trim size of file to certain size.
fn foo(f: &mut File) -> Result<(), Box<dyn Error>> {
    f.set_len(0)?;
    Ok(())
}

fn main () -> Result<(), Box<dyn Error>> {
    let mut buf = Vec::new();
    let mut mockfile = Cursor::new(&buf);
    // we would like to supply foo
    // with "test" representation of initial file state
    foo(&mut mockfile)
    // and check afterwards if resulting contents (=> size)
    // of file match expectations
}

在rust play上:https://play.rust-lang.org/?version=stable

错误:

error[E0308]: mismatched types
  --> src/main.rs:15:9
   |
15 |     foo(&mut mockfile)
   |         ^^^^^^^^^^^^^ expected struct `File`, found struct `std::io::Cursor`

P、 在收到答案之前,我开始尝试tempfile板条箱:https://docs.rs/tempfile/3.1.0/tempfile/#structs不过,理想的解决方案是“在内存中”,所以不能等待问题的答案:)。

共有1个答案

颛孙飞鸾
2023-03-14

简而言之,如果函数需要精确的类型,就不能模拟<code>std::fs::File——这不是Rust的工作方式。

但是,如果您可以控制< code>foo,那么您可以很容易地发明一个具有< code>set_len的特征,并使< code>foo成为该特征的泛型。由于这是您的特点,您可以为在其他地方定义的类型(如< code>File)实现它,这将使< code>foo()像以前一样接受< code>File。但是它也将接受实现该特征的任何东西,包括您在测试套件中创建的模拟类型。由于单态化,它的执行将和原始代码一样高效。例如:

pub trait SetLen {
    fn set_len(&mut self, len: u64) -> io::Result<()>;
}

impl SetLen for File {
    fn set_len(&mut self, len: u64) -> io::Result<()> {
        File::set_len(self, len)
    }
}

pub fn foo(f: &mut impl SetLen) -> Result<(), Box<dyn Error>> {
    f.set_len(0)?;
    Ok(())
}

// You can always pass a `File` to `foo()`:
fn main() -> Result<(), Box<dyn Error>> {
    let mut f = File::create("bla")?;
    foo(&mut f)?;
    Ok(())
}

要模拟它,您只需定义一个实现该特性的类型,并记录它是否被调用:

#[derive(Debug, Default)]
struct MockFile {
    set_len_called: Option<u64>,
}

impl SetLen for MockFile {
    fn set_len(&mut self, len: u64) -> io::Result<()> {
        self.set_len_called = Some(len);
        Ok(())
    }
}

#[test]
fn test_set_len_called() {
    let mut mf = MockFile::default();
    foo(&mut mf).unwrap();
    assert!(mf.set_len_called == Some(0));
}

游乐场

 类似资料:
  • 为了获得可重用和可测试的rxjava代码,我使用ObservableTransformers分离了代码的各个部分。它在生产中工作得很好,但是测试它并不像预期的那么容易,因为我似乎无法模拟那些观察到的ransformers。 when(observableTransformer.apply(any())).thenreturn(observable.just(“mockedtext”)); 一旦调用

  • 问题内容: 我有以下指令来自动聚焦字段: 我将如何对此进行单元测试?我尝试了以下选择器之类的几种方法,但是它们都返回错误或false: 我的单元测试设置如下: 问题答案: 我想通了,实际上这很明显。 我的问题有两个: 我没有调用超时刷新功能,所以没有发生超时,并且 我试图查看元素的focus属性,而仅关注focus()函数的调用更像是单元测试。focus属性确实属于e2e测试领域。

  • 因为我编码C已经超过20年了,我想我是时候参加一次测试了!看看我是不是学到了什么,或者我只是在网上给初学者发免费但不正确的建议。 这个网站(我不是附属)提供免费的C测试。https://www.tutorialspoint.com/cprogramming/cprogramming_mock_test.htm。

  • 问题内容: 我正在使用RestTemplate 方法发布到端点。在我的测试文件中,我正在测试POST方法。但是用我目前的测试,我得到了POST请求。在测试文件中发出POST请求时,我需要模拟API的帮助 这是我的主文件 这是我的测试文件 问题答案: 您正在测试DataTestRepo类内部的逻辑,因此您不应模拟它。RestTemplate是DataTestRepo内部的一个依赖项,因此这正是您需要

  • 在如何模拟Grails单元测试中使用的自动有线依赖方面,我可以提供一些建议。我省略了大部分不必要的代码,只给出了测试类和被测试文件类中的相关方法 如果不对此依赖性进行攻击或嘲弄,我就会得到错误 我尝试存根密码编码器并让它返回true 但这会给出一条错误消息: 有什么方法可以用Spock来嘲笑这种依赖吗?

  • 我在尝试包装我的代码以用于单元测试时遇到了一些问题。问题是。我有接口IHttpHandler: 现在很明显,我将在Connection类中有一些方法,这些方法将从my后端检索数据(JSON)。但是,我想为这个类编写单元测试,显然我不想编写针对真实后端的测试,而是一个被嘲弄的测试。我曾尝试谷歌一个很好的答案,但没有很大的成功。我以前可以并且曾经使用过Moq来模拟,但是从来没有在像HttpClient