TNG / ArchUnitNET

A C# architecture test library to specify and assert architecture rules in C# for automated testing.
Apache License 2.0
826 stars 55 forks source link

Static classes are verified as abstract classes. is this correct? #258

Closed jnormen closed 2 weeks ago

jnormen commented 2 months ago

I have a test where I check if I have abstract classes if so then I want it to check if the suffix is Base. But when I run the tests it complain on my Extensions classes and my Logger (source generated once.)

Non of them are marked as abstract. What do I miss? a bug? intented?

 [Fact]
    public void Abstract_Classes_Should_Have_Base_Suffix()
    {
        Classes()
            .That()
            .AreAbstract()
            .Should().HaveNameEndingWith("Base")
            .Because("It's a design rule to name the abstract classes with the suffix 'Base'.")
            .Check(Architecture);
    }

complain:

...
Infrastructure.Loggers.ServiceLogger does have name ServiceLogger
Lindex.Core.WebApi.EndpointsExtension does have name EndpointsExtension

example of an logger extension:

  public static partial class ServiceLogger
    {
        [LoggerMessage(
        Level = LogLevel.Information,
        EventName = "ServiceStarting",
        Message = "Start service '{ServiceName}'")]
        public static partial void ServiceStarting(this ILogger logger, string serviceName);

in this case it's partial.

   public static class EndpointsExtension
    {
        public static IEndpointRouteBuilder UseAllEndpoints(this IEndpointRouteBuilder builder)
        {
jnormen commented 2 months ago

Think I know why. seams IL treat static and abstract as same :(

mak638 commented 1 month ago

Hi, unfortunately this is correct - static classes are automatically treated as abstract. But they are treated as sealed as well! Therefore if you want to check only abstract classes that are non-static you could try the following workaround:

[Fact]
public void Abstract_Classes_Should_Have_Base_Suffix()
{
    Classes()
        .That()
        .AreAbstract()
        .And()
        .AreNotSealed()
        .Should().HaveNameEndingWith("Base")
        .Because("It's a design rule to name the abstract classes with the suffix 'Base'.")
        .Check(Architecture);
}

Please let me know if this workaround works for you. If so maybe we can further improve our Class class :)

jnormen commented 1 month ago

Cool that seams to work :) Did not know about the sealed thing. Maybe I shall check the IL more often :)