Swift Mock filesystem?

Hey everyone,

I'm currently writing some tests for my code (which reads from files and directories)
I was told to use a Mock filesystem instead of manually creating a bunch of directories / files into my test's setUp methods
Does anyone know if that's a good idea ? Is there any good library out there that'd "mock" the FileManager / URL library and let me create in-memory file?

No need for a library. Just use a protocol instead of actual filesystem APIs and create a mock implementation for unit tests and a real implementation for production. I did something similar for UserDefaults access.

It’s also fine to test writing real files. Purity for purity’s sake helps no one.

5 Likes

I have decided to opt for Bundles to feed pre existing files and directories for my tests to work against but I can't quite get a path to the bundles I have created

with my package.swift file being :

// swift-tools-version: 5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
  name: "Swatter",
  dependencies: [
    // Dependencies declare other packages that this package depends on.
    // .package(url: /* package url */, from: "1.0.0"),
    .package(url: "https://github.com/apple/swift-syntax.git", from: "0.50600.1"),
    .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
  ],
  targets: [
    // Targets are the basic building blocks of a package. A target can define a module or a test suite.
    // Targets can depend on other targets in this package, and on products in packages this package depends on.
    .executableTarget(
      name: "Swatter",
      dependencies: [
        .product(name: "SwiftSyntax", package: "swift-syntax"),
        .product(name: "ArgumentParser", package: "swift-argument-parser"),
      ]),
    .testTarget(
      name: "SwatterTests",
      dependencies: [
        "Swatter"
      ],
      resources: [.copy("ProjectTests")]),
  ]
)

my project structure being :
image

Calling this code

    let test = Bundle(for: type(of: self))
    print(test.bundlePath)

inside the test returns a result to the debug directory of my build "/home/infrandomness/Documents/Dev/Swatter/.build/x86_64-unknown-linux-gnu/debug"

and after a bit of searching around, the files are copied, but the returned bundlePath is not correct :

[infrandomness@fedora Swatter]$ find . -name Cartfile
./Tests/SwatterTests/ProjectTests/TestIsValidProject/Carthage/Cartfile <- original file
./.build/x86_64-unknown-linux-gnu/debug/Swatter_SwatterTests.resources/ProjectTests/TestIsValidProject/Carthage/Cartfile <- correct file path

One reason to use mocks is that they'll be faster than the actual APIs. This is likely true for Networking APIs but file system APIs are pretty fast anyway. I use the file system APIs directly in my tests with no problems.
If whoever told you to use file system mocks didn't tell you what mock library they use, well...