Skip to content

Commit 470585f

Browse files
test: add coverage for logError:eventInfo (#448)
* fully covered logError:eventInfo * Organized error tests file with marks * create helper for checking mock listenerController vars
1 parent fa1766c commit 470585f

File tree

3 files changed

+120
-12
lines changed

3 files changed

+120
-12
lines changed

UnitTests/Mocks/MPListenerControllerMock.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,67 @@ class MPListenerControllerMock: NSObject, MPListenerControllerProtocol {
4646
onAPICalledExpectation?.fulfill()
4747
}
4848
}
49+
50+
extension MPListenerControllerMock {
51+
52+
/// Verifies that the listener was called with the expected selector and parameters.
53+
/// Automatically checks `onAPICalledCalled`, the selector, and up to three parameters.
54+
func assertCalled(
55+
_ expectedSelector: Selector,
56+
param1 expectedParam1: NSObject? = nil,
57+
param2 expectedParam2: NSObject? = nil,
58+
param3 expectedParam3: NSObject? = nil,
59+
file: StaticString = #file,
60+
line: UInt = #line
61+
) {
62+
XCTAssertTrue(onAPICalledCalled, "Expected onAPICalled to be called", file: file, line: line)
63+
64+
guard let actualSelector = onAPICalledApiName else {
65+
XCTFail("Expected API name \(expectedSelector), but none was recorded", file: file, line: line)
66+
return
67+
}
68+
XCTAssertEqual(
69+
NSStringFromSelector(actualSelector),
70+
NSStringFromSelector(expectedSelector),
71+
"Expected API selector to match",
72+
file: file,
73+
line: line
74+
)
75+
76+
if let expectedParam1 {
77+
XCTAssertEqual(
78+
onAPICalledParameter1,
79+
expectedParam1,
80+
"Expected param1 to match for \(expectedSelector)",
81+
file: file,
82+
line: line
83+
)
84+
}
85+
86+
if let expectedParam2 {
87+
XCTAssertEqual(
88+
onAPICalledParameter2,
89+
expectedParam2,
90+
"Expected param2 to match for \(expectedSelector)",
91+
file: file,
92+
line: line
93+
)
94+
}
95+
96+
if let expectedParam3 {
97+
XCTAssertEqual(
98+
onAPICalledParameter3,
99+
expectedParam3,
100+
"Expected param3 to match for \(expectedSelector)",
101+
file: file,
102+
line: line
103+
)
104+
}
105+
}
106+
107+
/// Verifies that no API call occurred.
108+
func assertNotCalled(file: StaticString = #file, line: UInt = #line) {
109+
XCTAssertFalse(onAPICalledCalled, "Expected onAPICalled NOT to be called", file: file, line: line)
110+
XCTAssertTrue(onAPICalledApiNames.isEmpty, "Expected no recorded API names", file: file, line: line)
111+
}
112+
}

UnitTests/SwiftTests/MParticle/MParticleErrorTests.swift

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,88 @@ import XCTest
1414

1515
final class MParticleErrorTests: MParticleTestBase {
1616

17+
// MARK: - Properties
18+
19+
var errorMessage = "error"
20+
21+
// MARK: - logErrorCallback
22+
1723
func test_logErrorCallback_logsMessage_whenSuccess() {
18-
mparticle.logErrorCallback([:], execStatus: .success, message: "error")
19-
20-
assertReceivedMessage("Logged error with message: error")
24+
mparticle.logErrorCallback([:], execStatus: .success, message: errorMessage)
25+
assertReceivedMessage("Logged error with message: \(errorMessage)")
2126
}
2227

2328
func test_logErrorCallback_doesNotLog_whenFail() {
24-
mparticle.logErrorCallback([:], execStatus: .fail, message: "error")
25-
29+
mparticle.logErrorCallback([:], execStatus: .fail, message: errorMessage)
2630
XCTAssertNil(receivedMessage)
2731
}
2832

33+
// MARK: - logExceptionCallback
34+
2935
func test_logExceptionCallback_logsDetails_whenSuccess() {
3036
mparticle.logExceptionCallback(exception, execStatus: .success, message: "exception", topmostContext: nil)
31-
3237
assertReceivedMessage("Logged exception name: exception, reason: Test, topmost context: (null)")
3338
}
3439

3540
func test_logExceptionCallback_doesNotLog_whenFail() {
3641
mparticle.logExceptionCallback(exception, execStatus: .fail, message: "exception", topmostContext: nil)
37-
3842
XCTAssertNil(receivedMessage)
3943
}
4044

45+
// MARK: - logCrashCallback
46+
4147
func test_logCrashCallback_logsMessage_whenSuccess() {
42-
mparticle.logCrashCallback(.success, message: "Message")
43-
assertReceivedMessage("Logged crash with message: Message")
48+
mparticle.logCrashCallback(.success, message: errorMessage)
49+
assertReceivedMessage("Logged crash with message: \(errorMessage)")
4450
}
4551

52+
// MARK: - logNetworkPerformanceCallback
53+
4654
func test_logNetworkPerformanceCallback_logsMessage_whenSuccess() {
4755
mparticle.logNetworkPerformanceCallback(.success)
48-
4956
assertReceivedMessage("Logged network performance measurement")
5057
}
5158

5259
func test_logNetworkPerformanceCallback_doesNotLog_whenFail() {
5360
mparticle.logNetworkPerformanceCallback(.fail)
54-
5561
XCTAssertNil(receivedMessage)
5662
}
63+
64+
// MARK: - logError
65+
66+
func test_logError_withoutEventInfo_invokesBackendWithNil() {
67+
mparticle.logError(errorMessage)
68+
69+
XCTAssertTrue(executor.executeOnMessageQueueAsync)
70+
listenerController.assertCalled(#selector(mparticle.logError(_:eventInfo:)))
71+
72+
XCTAssertTrue(backendController.logErrorCalled)
73+
XCTAssertNil(backendController.logErrorExceptionParam)
74+
XCTAssertNil(backendController.logErrorTopmostContextParam)
75+
XCTAssertNil(backendController.logErrorEventInfoParam)
76+
77+
backendController.logErrorCompletionHandler?(errorMessage, .success)
78+
assertReceivedMessage("Logged error with message: \(errorMessage)")
79+
}
80+
81+
func test_logError_withNilMessage_logsRequirementMessage() {
82+
errorMessage = ""
83+
mparticle.logError(errorMessage, eventInfo: keyValueDict)
84+
assertReceivedMessage("'message' is required for logError:eventInfo:")
85+
}
86+
87+
func test_logError_withMessage_invokesBackend() {
88+
mparticle.logError(errorMessage, eventInfo: keyValueDict)
89+
90+
XCTAssertTrue(executor.executeOnMessageQueueAsync)
91+
listenerController.assertCalled(#selector(mparticle.logError(_:eventInfo:)))
92+
93+
XCTAssertTrue(backendController.logErrorCalled)
94+
XCTAssertNil(backendController.logErrorExceptionParam)
95+
XCTAssertNil(backendController.logErrorTopmostContextParam)
96+
XCTAssertEqual(backendController.logErrorEventInfoParam as? [String : String], keyValueDict)
97+
98+
backendController.logErrorCompletionHandler?(errorMessage, .success)
99+
assertReceivedMessage("Logged error with message: \(errorMessage)")
100+
}
57101
}

mParticle-Apple-SDK/mParticle.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ - (void)logErrorCallback:(NSDictionary<NSString *,id> * _Nullable)eventInfo exec
10911091
}
10921092

10931093
- (void)logError:(NSString *)message eventInfo:(NSDictionary<NSString *, id> *)eventInfo {
1094-
if (!message) {
1094+
if ([message isEqual: @""]) {
10951095
NSString *message = [NSString stringWithFormat:@"'message' is required for %@", NSStringFromSelector(_cmd)];
10961096
[logger error:message];
10971097
return;

0 commit comments

Comments
 (0)