InjectableLoggers 2.1.1

InjectableLoggers 2.1.1

Maintained by Menno Lovink.


Version Platform License

A nice set of protocols that will help logger(s) at being loosely coupled, injectable and testable.


To see the example project, run the following in your terminal:

pod try InjectableLoggers


Just add:

import InjectableLoggers

to the files where you need some injectable logging action.

Making your logger injectable

Depending on how much functionality you want (to expose) from a logger, make a logger conform to one of the following protocols:




All of thes protocols have lightweight and sensible default implementations and make sure you never have to implement more than one of their methods.

Making an existing logger injectable

When it uses instance methods for logging

extension SomeoneElsesLogger: CanLogMessageAtLevel /* CanLog || CanLogMessage */ {

	func log(_ message Any, at: LogLevel) {
		//call existing logging functionality here

When it uses class methods for logging

struct Logger: CanLogMessageAtLevel /* CanLog || CanLogMessage */ {

	func log(_ message Any, at: LogLevel) {
		//call existing logging functionality here

Doing some logging

Depending on which protocols your loggers conform to, you can call the following methods:

logger.log() //Will log "" to default LogLevel if expected
logger.log(42) //Will log 42 to default LogLevel if expected
logger.log("Something not to important", at LogLevel.verbose)
logger.log("Something broke!", at: LogLevel.error)

Bonus! This lib comes with two concrete loggers 🎉


let logger: CanLogMessage = ConsoleLogger()

logger.log() // logs to console: ""
logger.log(42) // logs to console: 42
logger.log("Hi there") // logs to console: "Hi there"


let logger: CanLogMessageAtLevel = Logger(settings: .warningSettings)

logger.log("Some info", atLevel //Won't log anything because of settings
logger.log("Something's up") // logs to settings.destination: "⚠️ Something's up"
logger.log("Something went wrong") // logs to settings.destination: "⛔️ Something's up"


Yes, settings has it's own CanLogMessage instance (ConsoleLogger by default) which is used for logging all created strings. This not only made Logger completely testable (and tested) but it also allows you to log to different destinations if needed.

Testing that what was expected is being logged

Another bonus! This lib comes with a pretty handy mock logger called MockLogger 🎉

class ViewControllerTests: XCTestCase {
    var sut: ViewController!
    var mockLogger: MockLogger!
    override func setUp() {
        sut = ViewController()
        mockLogger = MockLogger()
    // MARK: Single line assertions
    func testViewDidLoad() {
        sut.logger = mockLogger //Inject mockLogger
        XCTAssertEqual(mockLogger.loggedMessages(at: as? String, "viewDidLoad()")
    // MARK: More verbose assertions
    func testDidReceiveMemoryWarning() {
        sut.logger = mockLogger //Inject mockLogger
        XCTAssertEqual(mockLogger.loggedMessages.last?.message as? String, "didReceiveMemoryWarning()")
        XCTAssertEqual(mockLogger.loggedMessages.last?.level, Loglevel.warning)

For some more advance testing check out the example project.


InjectableLoggers is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'InjectableLoggers'


InjectableLoggers is available under the MIT license. See the LICENSE file for more info.