-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NSubstitute makes it impossible to unit test memory leaks #771
Comments
@albyrock87 Thank you for the issue and great repro! public class NSubstituteLeakTests
{
public class Foo;
[Fact(DisplayName = "NSubstitute does not leak")]
public async Task NSubstituteDoesNotLeak()
{
WeakReference<Foo> weakFoo;
{
var foo = new Foo();
weakFoo = new WeakReference<Foo>(foo);
}
await Task.Yield();
GC.Collect();
GC.WaitForPendingFinalizers();
weakFoo.TryGetTarget(out _).Should().BeFalse();
}
} |
@alexandrnikitin I was pretty sure about the issue so I double checked again, and as you can see from this screenshot, the test without NSubstitute is working (see the green mark on the left side) This makes me think we're running the unit test on different frameworks. My XUnit test project is using <PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" PrivateAssets="all" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> |
Here's a test that fails for me on Windows and .NET 8 #775 |
@alexandrnikitin this is what Microsoft does to test leaks Anyway let's try with this: public class NSubstituteLeakTests
{
public class Foo;
public interface IInterface
{
public void Method(Foo foo);
}
// private readonly IInterface _interfaceMock = Substitute.For<IInterface>();
[Fact(DisplayName = "NSubstitute does not leak")]
public async Task NSubstituteDoesNotLeak()
{
WeakReference<Foo> weakFoo;
{
var foo = new Foo();
weakFoo = new WeakReference<Foo>(foo);
// _interfaceMock.Method(foo);
// _interfaceMock.ClearReceivedCalls();
}
await GcCollect();
weakFoo.TryGetTarget(out _).Should().BeFalse();
}
private static async Task GcCollect()
{
for (var i = 0; i < 3; i++)
{
await Task.Yield();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
} |
Describe the bug
I'm trying to test memory leaks on my library, but NSubstitute retains reference to call arguments (even after
ClearReceivedCalls
).This makes it impossible to test memory leaks which in some part require mocked interfaces.
To Reproduce
The following unit test fails.
This is what retains the reference to the object.
Expected behaviour
Unit test above passes.
Environment:
The text was updated successfully, but these errors were encountered: