Closed cfuehrmann closed 5 months ago
thank you for opening an issue for this. I may have a workaround for you: could add a Stryker comments above the problematic line ?
such as :
// Stryker disable once all
or // Stryker disable once Linq
The mutant will still be generated but no attempt to inject it should happen. It will be reported as Ignored
.
once you have pinpointed the offending line(s) could you please share the whole method so we can reproduce the problem and fix it properly ?
I've encountered a similar issue with .NET 6 and Flurl. The error is "Cannot inject mutation '$""' in 'IsSuccessStatusCode' because we cannot find the original code." and has a stack trace similar to the OP. It is interesting that this is taking that bool (IsSuccessStatusCode) from the System.Net.Http.HttpResponseMessage and trying to change it to a string. I hope this helps in investigating this issue. Thank you for the workaround.
@CrouseN : thanks for the report. Could you please share the method where you encounter the issue ? What happens here is what we call a 'mutation leak', i.e. a mutation from some syntax construct was not injected at the right place and then Stryker to inject it on some other bit of code. This is due to the fact that mutation generation and mutation injection do not happen in a close sequence (for reasons that are long to explain).
@dupdob Thanks for you quick response! I did as you requested. The file with the problem has three similar methods, below you can see one of them. The problematic line is the one containing group.First()
, directly underneath the // Stryker disable once all
, which I just added. That suppression, when added in all three above-mentioned methods, does indeed remove the problem. (Unlike your suggestion above, the suppression line contains no colon. With a colon, it did not work.)
private List<WorkflowTimePermissionsReadResponse> GetTimePermissionResponse(
IEnumerable<WorkflowRequestsReadOpenApi> openApiResponse)
{
return openApiResponse
.Where(_ => true)
.Where(response => response.Entitlement is not null)
.GroupBy(request => request.Entitlement!.Employee.Id)
.Select(group =>
{
// Stryker disable once all
var employeePerson = group.First().Entitlement!.Employee.Person;
return new WorkflowTimePermissionsReadResponse
{
EmployeeFirstName = employeePerson?.FirstName,
EmployeeMiddleName = employeePerson?.MiddleName,
EmployeeLastName = employeePerson?.LastName,
EmployeeId = group.Key,
PendingRequests = group
.Where(request => request.RequestState is WorkflowRequestStateOpenApi.Open)
.GroupBy(request => request.Status)
.SelectMany(grouping => grouping.ToList())
.Select(timePermission => new WorkflowTimePermissionResponse
{
RequestId = timePermission.Id,
RequestStatus = WorkflowConverter.FromOpenApi(timePermission.Status,
_logger),
RequestedOn = timePermission.CreationDate,
FromDay = DateOnly.FromDateTime(timePermission.Entitlement!.FromDate),
ToDay = DateOnly.FromDateTime(timePermission.Entitlement.ToDate),
RequesterComment = timePermission.RequestorComment,
AvailableActions = timePermission.AvailableActions
.Select(action => WorkflowConverter.FromOpenApi(action,
_logger))
.ToList(),
TimePermissionName = timePermission.Entitlement.Entitlement.Name,
TimePermissionValue =
timePermission.RequestedAction is WorkflowRequestedActionOpenApi.Create
}).ToList(),
ApprovedRequests = group
.Where(request => request.RequestState is WorkflowRequestStateOpenApi.Done)
.GroupBy(request => request.Status)
.Where(statusGroup =>
statusGroup.Key is WorkflowRequestStatusOpenApi.Agreed
or WorkflowRequestStatusOpenApi.Approved)
.SelectMany(grouping => grouping.ToList())
.Select(timePermission => new WorkflowTimePermissionResponse
{
RequestId = timePermission.Id,
RequestStatus = WorkflowConverter.FromOpenApi(timePermission.Status,
_logger),
RequestedOn = timePermission.CreationDate,
FromDay = DateOnly.FromDateTime(timePermission.Entitlement!.FromDate),
ToDay = DateOnly.FromDateTime(timePermission.Entitlement.ToDate),
RequesterComment = timePermission.RequestorComment,
AvailableActions = timePermission.AvailableActions
.Select(action => WorkflowConverter.FromOpenApi(action,
_logger))
.ToList(),
TimePermissionName = timePermission.Entitlement.Entitlement.Name,
TimePermissionValue =
timePermission.RequestedAction is WorkflowRequestedActionOpenApi.Create
}).ToList(),
DeniedRequests = group
.Where(request => request.RequestState is WorkflowRequestStateOpenApi.Done)
.GroupBy(request => request.Status)
.Where(statusGroup => statusGroup.Key is
WorkflowRequestStatusOpenApi.Rejected)
.SelectMany(grouping => grouping.ToList())
.Select(timePermission => new WorkflowTimePermissionResponse
{
RequestId = timePermission.Id,
RequestStatus = WorkflowConverter.FromOpenApi(timePermission.Status,
_logger),
RequestedOn = timePermission.CreationDate,
FromDay = DateOnly.FromDateTime(timePermission.Entitlement!.FromDate),
ToDay = DateOnly.FromDateTime(timePermission.Entitlement.ToDate),
RequesterComment = timePermission.RequestorComment,
AvailableActions = timePermission.AvailableActions
.Select(action => WorkflowConverter.FromOpenApi(action,
_logger))
.ToList(),
TimePermissionName = timePermission.Entitlement.Entitlement.Name,
TimePermissionValue =
timePermission.RequestedAction is WorkflowRequestedActionOpenApi.Create
}).ToList()
};
}).ToList();
}
Thanks for the sample and correcting my work around (did provide it on a memory basis, failed to verify the proper syntax). I think I have enough information to try and reproduce it. Will keep you informed on my progress
I just opened a PR with the (very) likely fix for this. Thanks for your helpful contributions
note that I have no valid explanation of why this issue appears in V3.13. My understanding is that it is a long standing issue.
note that I have no valid explanation of why this issue appears in V3.13. My understanding is that it is a long standing issue.
That's strange, thanks for letting me know. I really tested with V3.12, and the error did not occur.
my guess is that this problem was hidden by some other limitation/issue, that has been lifted/fix in V 3.13
Now that dotnet-stryker 3.13.2 is available, I could test it. The problem I had is indeed fixed. Thanks!
Describe the bug A "cannot inject mutation" error has appeared in version 3.13. The error did not occur with 3.12.1. The console output of
dotnet stryker --log-to-file
is here:CannotInjectMutation.log
The (main?) log file written by Stryker is here:
log-20240108.txt
Expected behavior Stryker should succeed on the .NET project in question.
Desktop (please complete the following information):
Additional context I have a .NET 6 solution containing a dozen projects, on several of which I run Stryker. Since the update from Stryker 3.12 to 3.13, one of those projects causes Stryker to fail with "cannot inject mutation". Apparently when Stryker tries to mutate a
.First()
into a.FirstOrDefault()
. Possibly important: The mutated statements are inside an anonymous function inside a LINQSelect
: