Open simonthum opened 1 year ago
I would also like to implement a test that only certain types can access the system time. However, the solution mentioned by @simonthum unfortunately does not work for me.
I tried unsuccessfully with
Classes().Should().NotCallAny(MethodMembers().That().AreDeclaredIn(typeof(System.DateTimeOffset)));
However, this is reasonable to me since _ = DateTimeOffset.Now
is an access to a property.
However, I cannot replace MethodMembers
with PropertyMembers
because the result is not accepted by NotCallAny
.
I wonder if there is a way to check for property access, or is this functionality not (yet) part of ArchUnitNET?
I was wrong -- Properties are a C# feature which are transformed into methods by the compiler. After specifying an empty parameter list and adding the assembly of DateTimeOffset
to the architecture, it worked:
var rule = Types().That().ResideInAssembly(myAssembly).Should().NotCallAny("System.DateTimeOffset::get_Now()");
I didn't find a way to define the rule strongly typed either. For the meantime I'm using an extension method. Maybe this is an acceptable workaround for others.
// Extension method
public static IArchRule NotAccessGetter<TType>(this ObjectsShould<TypesShouldConjunction, IType> builder, object? property, [CallerArgumentExpression("property")] string typeAndPropertyName = null!)
{
var names = typeAndPropertyName.Split('.');
if (names[0] != typeof(TType).Name) throw new ArgumentException($"'{names[1]}' is not part of '{names[0]}'.");
return builder.NotCallAny(MethodMembers().That().AreDeclaredIn(typeof(TType)).And().HaveName($"get_{names[1]}()"));
}
// Usage example
[Fact]
public void Test1()
{
// Remember to add the assembly that contains DateTimeOffset to your `architecture`.
var types = Types().That().ResideInAssembly(myAssembly);
types.Should().NotAccessGetter<DateTimeOffset>(DateTimeOffset.Now).Check(architecture);
types.Should().NotAccessGetter<DateTimeOffset>(DateTimeOffset.UtcNow).Check(architecture);
}
@x789 I like that creative solution, although having to actually call the Property may make it difficult to use in some contexts.
I have difficulties checking for unwanted system references - I failed to jot them down in a statically typed way.
Consider:
This works but is not exactly intuitive. I went on to try:
But there is no
MethodMembers(true)
that would allow to check for members of system types this way.Is there another way I'm missing to achieve rule1 statically typed?