Skip to content

Commit

Permalink
Added test for the static method based LoggerService
Browse files Browse the repository at this point in the history
  • Loading branch information
rob-baillie-ortoo committed Apr 7, 2022
1 parent 778cafc commit 41658f9
Show file tree
Hide file tree
Showing 2 changed files with 387 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,382 @@
@isTest
private without sharing class LoggerServiceTest
{
@isTest
private static void log_whenGivenALevelAndAMessageAndLoggingIsEnabledForThatLevel_callsToLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.INFO;
String message = 'the message';

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_INFO_Level_Messages__c = true );

Test.startTest();
LoggerService.log( level, message );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given a level and a message, and logging is enabled for that level, calls the service to log' );
System.assertEquals( new List<Object>{ level, message }, fakeLogger.parameters[0], 'log, when given a level and a message, and logging is enabled for that level, calls the service to log, passing parameters' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndLoggingIsDisabledForThatLevel_doesNotCallToLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.INFO;
String message = 'the message';

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_INFO_Level_Messages__c = false );

Test.startTest();
LoggerService.log( level, message );
Test.stopTest();

System.assert( fakeLogger.methods.isEmpty(), 'log, when given a level and a message, and logging is disabled for that level, does not call against the service' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndLoggingAndNoConfig_asksServiceIfItShouldLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.INFO;
String message = 'the message';

FakeLogger fakeLogger = new FakeLogger().setDefaultLoggingEnabledReturns( true );
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c(); // nameless config means there's no config

Test.startTest();
LoggerService.log( level, message );
Test.stopTest();

System.assertEquals( 'getDefaultLoggingEnabled', fakeLogger.methods[0], 'log, when given a level and a message, and config is missing, asks the service if it should log' );
System.assertEquals( LoggerService.Level.INFO, fakeLogger.parameters[0][0], 'log, when given a level and a message, and config is missing, and config is missing, asks the service if it should log' );

System.assertEquals( 'log', fakeLogger.methods[1], 'log, when given a level and a message, and config is missing, asks the service if it should log, and calls the service if it should' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndLoggerThrowsException_doesNotThrow() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.INFO;
String message = 'the message';

FakeLogger fakeLogger = new FakeLogger().loggingThrowsException();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_INFO_Level_Messages__c = true );

Test.startTest();
LoggerService.log( level, message );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given a level and a message, and the logger throws an exception, does not throw' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndIdAndLoggingIsEnabledForThatLevel_callsToLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.WARN;
String message = 'the message';
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_WARN_Level_Messages__c = true );

Test.startTest();
LoggerService.log( level, message, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given a level and a message and sobject id, and logging is enabled for that level, calls the service to log' );
System.assertEquals( new List<Object>{ level, message, relatedSobjectId }, fakeLogger.parameters[0], 'log, when given a level and a message, and sobject id and logging is enabled for that level, calls the service to log, passing parameters' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndIdAndLoggingIsDisabledForThatLevel_doesNotCallToLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.WARN;
String message = 'the message';
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_WARN_Level_Messages__c = false );

Test.startTest();
LoggerService.log( level, message, relatedSobjectId );
Test.stopTest();

System.assert( fakeLogger.methods.isEmpty(), 'log, when given a level and a message and sobject id, and logging is disabled for that level, does not call against the service' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndIdAndLoggingAndNoConfig_asksServiceIfItShouldLog() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.WARN;
String message = 'the message';
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger().setDefaultLoggingEnabledReturns( true );
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c(); // nameless config means there's no config

Test.startTest();
LoggerService.log( level, message, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'getDefaultLoggingEnabled', fakeLogger.methods[0], 'log, when given a level and a message and sobject id, and config is missing, asks the service if it should log' );
System.assertEquals( LoggerService.Level.WARN, fakeLogger.parameters[0][0], 'log, when given a level and a message and sobject id, and config is missing, and config is missing, asks the service if it should log' );

System.assertEquals( 'log', fakeLogger.methods[1], 'log, when given a level and a message and sobject id, and config is missing, asks the service if it should log, and calls the service if it should' );
}

@isTest
private static void log_whenGivenALevelAndAMessageAndIdAndLoggerThrowsException_doesNotThrow() // NOPMD: Test method name format
{
LoggerService.Level level = LoggerService.Level.WARN;
String message = 'the message';
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger().loggingThrowsException();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_WARN_Level_Messages__c = true );

Test.startTest();
LoggerService.log( level, message, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given a level and a message and sobject id, and the logger throws an exception, does not throw' );
}

@isTest
private static void log_whenGivenExceptionAndLoggingIsEnabledForThatLevel_callsToLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = true );

Test.startTest();
LoggerService.log( exceptionToLog );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given an exception, and logging is enabled for that level, calls the service to log' );
}

@isTest
private static void log_whenGivenExceptionAndLoggingIsDisabledForErrors_doesNotCallToLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = false );

Test.startTest();
LoggerService.log( exceptionToLog );
Test.stopTest();

System.assert( fakeLogger.methods.isEmpty(), 'log, when given an exception, and logging is disabled for errors, does not call against the service' );
}

@isTest
private static void log_whenGivenExceptionAndLoggingAndNoConfig_asksServiceIfItShouldLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );

FakeLogger fakeLogger = new FakeLogger().setDefaultLoggingEnabledReturns( true );
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c(); // nameless config means there's no config

Test.startTest();
LoggerService.log( exceptionToLog );
Test.stopTest();

System.assertEquals( 'getDefaultLoggingEnabled', fakeLogger.methods[0], 'log, when given an exception, and config is missing, asks the service if it should log' );
System.assertEquals( LoggerService.Level.ERROR, fakeLogger.parameters[0][0], 'log, when given an exception, and config is missing, asks the service if it should log' );

System.assertEquals( 'log', fakeLogger.methods[1], 'log, when given an exception, and config is missing, asks the service if it should log, and calls the service if it should' );
}

@isTest
private static void log_whenGivenExceptionAndLoggerThrowsException_doesNotThrow() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );

FakeLogger fakeLogger = new FakeLogger().loggingThrowsException();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = true );

Test.startTest();
LoggerService.log( exceptionToLog );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given an exception, and the logger throws an exception, does not throw' );
}

@isTest
private static void log_whenGivenExceptionAndIdAndLoggingIsEnabledForThatLevel_callsToLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = true );

Test.startTest();
LoggerService.log( exceptionToLog, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given an exception and an id, and logging is enabled for that level, calls the service to log' );
}

@isTest
private static void log_whenGivenExceptionAndIdAndLoggingIsDisabledForErrors_doesNotCallToLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = false );

Test.startTest();
LoggerService.log( exceptionToLog, relatedSobjectId );
Test.stopTest();

System.assert( fakeLogger.methods.isEmpty(), 'log, when given an exception and an id, and logging is disabled for errors, does not call against the service' );
}

@isTest
private static void log_whenGivenExceptionAndIdAndLoggingAndNoConfig_asksServiceIfItShouldLog() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger().setDefaultLoggingEnabledReturns( true );
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c(); // nameless config means there's no config

Test.startTest();
LoggerService.log( exceptionToLog, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'getDefaultLoggingEnabled', fakeLogger.methods[0], 'log, when given an exception and an id, and config is missing, asks the service if it should log' );
System.assertEquals( LoggerService.Level.ERROR, fakeLogger.parameters[0][0], 'log, when given an exception and an id, and config is missing, asks the service if it should log' );

System.assertEquals( 'log', fakeLogger.methods[1], 'log, when given an exception and an id, and config is missing, asks the service if it should log, and calls the service if it should' );
}

@isTest
private static void log_whenGivenExceptionAndIdAndLoggerThrowsException_doesNotThrow() // NOPMD: Test method name format
{
Exception exceptionToLog = new LocalException( 'message' );
Id relatedSobjectId = TestIdUtils.generateId( Contact.SobjectType );

FakeLogger fakeLogger = new FakeLogger().loggingThrowsException();
Application.SERVICE.setMock( ILoggerService.class, fakeLogger );

LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_ERROR_Level_Messages__c = true );

Test.startTest();
LoggerService.log( exceptionToLog, relatedSobjectId );
Test.stopTest();

System.assertEquals( 'log', fakeLogger.methods[0], 'log, when given an exception and an id, and the logger throws an exception, does not throw' );
}

@isTest
private static void log_whenTheLoggerCannotBeFound_usesANullLogger() // NOPMD: Test method name format
{
Application.SERVICE.setMock( ILoggerService.class, null );
LoggerService.config = new Logging_Configuration__c( Name = 'Name', Log_INFO_Level_Messages__c = true );

Test.startTest();
LoggerService.log( LoggerService.Level.INFO, 'message' );
Test.stopTest();

System.assert( true, 'log, when the logger service implementation cannot be found, will use a null logger and no exception is thrown' );
}

class LocalException extends Exception {}
// This exists because StubProvider has difficulty creating a stub for ILoggerService
// Potentially it's a problem with overloaded methods defined in an interface.
class FakeLogger implements ILoggerService
{
public List<String> methods = new List<String>();
public List<List<Object>> parameters = new List<List<Object>>();
Boolean defaultLoggingEnabledReturns = false;
Boolean loggingThrowsException = false;

public FakeLogger loggingThrowsException()
{
loggingThrowsException = true;
return this;
}
public FakeLogger setDefaultLoggingEnabledReturns( Boolean returns )
{
defaultLoggingEnabledReturns = returns;
return this;
}
public Boolean getDefaultLoggingEnabled( LoggerService.Level logLevel )
{
methods.add( 'getDefaultLoggingEnabled' );
parameters.add( new List<Object>{ logLevel } );
return defaultLoggingEnabledReturns;
}
public void log( LoggerService.Level logLevel, String message )
{
methods.add( 'log' );
parameters.add( new List<Object>{ logLevel, message } );
if ( loggingThrowsException )
{
throw new LocalException( 'a message' );
}
}
public void log( LoggerService.Level logLevel, String message, Id relatedSobjectId )
{
methods.add( 'log' );
parameters.add( new List<Object>{ logLevel, message, relatedSobjectId } );
if ( loggingThrowsException )
{
throw new LocalException( 'a message' );
}
}
public void log( Exception exceptionToLog )
{
methods.add( 'log' );
parameters.add( new List<Object>{ exceptionToLog } );
if ( loggingThrowsException )
{
throw new LocalException( 'a message' );
}
}
public void log( Exception exceptionToLog, Id relatedSobject )
{
methods.add( 'log' );
parameters.add( new List<Object>{ exceptionToLog, relatedSobject });
if ( loggingThrowsException )
{
throw new LocalException( 'a message' );
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<status>Active</status>
</ApexClass>

0 comments on commit 41658f9

Please sign in to comment.