-
Notifications
You must be signed in to change notification settings - Fork 7
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
NS2001: Is an accessible constructor strictly necessary? #227
Comments
Hi @stogle
Yes it is. Here is a minimal repro showing that NSubstitute will fail to create substitute for class with only internal ctor public class Test
{
[Fact]
public void Foo()
{
var substitute = Substitute.For<MyAbstractClass>();
_ = substitute;
}
}
public abstract class MyAbstractClass
{
internal MyAbstractClass()
{
}
} When it comes to your case, it looks like Avalonia marks their assembly with |
Hi @tpodolak, thanks for the answer! I did not think to look for the InternalsVisibleTo attribute, but that makes total sense.
Either way, I now have a proper justification for disabling the warning in this case. Thanks again. |
I'm not that familiar with Roslyn or writing analyzers, but I think what you are saying is that NSubstitute can see this constructor in Avalonia.Base.dll at runtime, but NSubstitute.Analyzers can't see it during analysis, even though it normally sees internal constructors on other assemblies that use If it would help, I could create an Issue or a Discussion in the Avalonia repository about this. I'm just not sure what to say. Still, using a #pragma to disable this particular warning isn't a big deal for me, as long as I have a justification. |
In my unit test I am creating a substitute for this third-party public abstract class, which has only an empty internal constructor. I am getting an NS2001 warning because the constructor is not accessible from the test, however the substitute and my test appear to work as intended. All my test does with the substitute is pass it to my method-under-test, then manually check its
ReceivedCalls()
list. It does not set any return values or anything else. (I can't share my actual test for IP reasons, but I can create a minimal example if that would help.)I understand the problems associated with substituting for classes rather than interfaces, and that non-virtual code is executed during my test. What I'm not clear on is the specific problems with violating NS2001 by substituting for a class with an inaccessible constructor. The rule says that to fix this violation I should add an accessible constructor to the type, but I can't do that because I don't own the type. Furthermore, NSubstitute is still able to create a substitute without an accessible constructor (presumably via reflection).
Could the documentation for the rule expand on why an accessible constructor is important and what happens when you create a substitute for a class without one?
The text was updated successfully, but these errors were encountered: