Skip to content

[Bug] Mock doesn't record every invocation when invoked simultaneously across threads #121

@graycampbell

Description

@graycampbell

Swift Version

6.0

Package Version

0.2.1

Bug Description

I ran unit tests for a method that awaited a task group. In the task group, in each task, I call a method on a dependency. In the tests, I injected a mock and asserted that the mock's method was called a certain number of times (in this case twice), and that the invocations array contained the expected arguments. Instead of always getting two invocations, I sometimes only got one. The method's call count also sometimes came back as one instead of two.

Steps to Reproduce

Create a task group that adds a certain number of tasks and have each task call a method on a dependency. Make the work inside the tasks synchronous to ensure they all finish at the same time. Inject a mock and assert that the mock's method is called more than once.

Additional Context

Inside the mock method's recordInput method, the call count and invocations are being accessed via wrapper properties that then access locked backing properties. The problem is that the wrapper properties' getters and setters are being protected separately by their respective lock, so:

Thread 1: Lock; read callCount; see it’s 0; unlock
Thread 2: Lock; read callCount; see it’s 0; unlock
Thread 1: Lock; set callCount to 1; unlock
Thread 2: Lock; set callCount to 1; unlock

The same thing happens with invocations.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions