I realise that this is quite late but I just wanted to share my solution with using jest, since I wasn't entirely satisfied with the solutions found here. I can't say my solution is very elegant and may just be hiding some code smell as I'm still learning TDD, but it works.
In my work I often want to log to a file specified via a winston.transports.File(filename: "<filename>") transport. Let's say my log file is info.log
Of course, during testing, I don't want
- logs to be written to this 
info.log 
info.log to be created if it doesn't exist. 
This is so to avoid side-effects. The answers above along with mocking were enough for avoiding 1. but for some reason did not avoid 2. (explained why below) .
The way I set up my projects is usually as such 
   src
    ├── app.js
    ├── services
    │   ├── logging
    │   │   ├── logger.js
    │   │   └── logger_utils.js
    │   ├── foo.js
    │   ├── bar.js
    │   └── etc.js
    ├── tests
    │   ├── foo.test.js
    │   ├── bar.test.js
    │   └── etc.test.js
    └── logs
        └── info.log
Focus mostly on the log-related files. logger.js is where I instantiate and subsequently export the winston Logger object. I then write helper functions in logger_utils.js for modularity and easier testing. 
When my issue was appearing, logger.js consisted in
problematic_logger.js
const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "./../../logs/info.log");
// create logger
const logger = winston.createLogger({
    transports: [
      new winston.transports.File({
        filename: log_dir
      })
    ]
  });
// export it
module.exports = logger;
I then required it in logger_utils.js which would in turn be required in any other modules scripts. So, in testing (apart from testing logger_utils.js), I only need to mock functions contained in logger_utils.js, with no need to worry about logger.js, since it is only called by logger_utils.js. 
Now, I'm not entirely sure about this, but I think 2. defined above still failed despite the mocks and the silencing because winston.createLogger() was still being called, and I believe this will create a file even when a --silent flag is set. I don't know if this is true, but nevertheless the solutions above weren't working. 
So, (inspired by this answer) what I decided to do is to simply not create any winston object when testing. I did this by changing my logger.js file to
fixed_logger.js
const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "../../logs/info.log");
// if we are testing, don't create any winston object
if (process.env.NODE_ENV === "test") {
  // export
  module.exports = {};
} else {
  // behave normally otherwise
  // create winston logger
  const logger = winston.createLogger({
    transports: [
      new winston.transports.File({
        filename: log_dir
      })
    ]
  });
  // export it
  module.exports = logger;
}
(NODE_ENV is automatically set to "test" when running npm test or npm run test:watch etc.)
We still need to export something for logger_utils.js to not break when testing it, so we export an empty object. This is fine since it will be mocked.
Anyway, that's my first answer on stackoverflow out of the way. I hope it wasn't too disastrous, let me know if anyone wants further details.