Skip to content

Commit d150dc9

Browse files
authored
Added non Generic ClassConstructorAttribute for F# and VB.NET (#2402)
* Created ClassConstructorTest for VB and F# * Update ClassConstructorAttribute.cs * ClassConstructorWithEnumeralTest for VB & F# * code quality fixes * Updated PublicAPI for TUnit.Core
1 parent ed1807d commit d150dc9

14 files changed

+222
-17
lines changed
Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
1-
using System.Diagnostics.CodeAnalysis;
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
23
using TUnit.Core.Interfaces;
34

45
namespace TUnit.Core;
56

6-
public abstract class ClassConstructorAttribute : TUnitAttribute, IDataAttribute
7+
// Base abstract class
8+
public abstract class BaseClassConstructorAttribute : TUnitAttribute, IDataAttribute
79
{
8-
public abstract Type ClassConstructorType { get; }
10+
public abstract Type ClassConstructorType { get; set; }
911

10-
internal ClassConstructorAttribute()
12+
private protected BaseClassConstructorAttribute() { }
13+
private protected BaseClassConstructorAttribute(Type classType) { ClassConstructorType = classType; }
14+
}
15+
16+
// Single sealed attribute with both generic and non-generic constructors
17+
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class)]
18+
public class ClassConstructorAttribute : BaseClassConstructorAttribute
19+
{
20+
public ClassConstructorAttribute(Type classConstructorType)
21+
: base(classConstructorType)
1122
{
23+
ClassConstructorType = classConstructorType;
1224
}
25+
26+
public override Type ClassConstructorType { get; set; }
1327
}
1428

29+
// Generic version for C#
1530
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class)]
16-
public sealed class ClassConstructorAttribute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>
17-
: ClassConstructorAttribute where T : IClassConstructor, new()
31+
public sealed class ClassConstructorAttribute<
32+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>()
33+
: ClassConstructorAttribute(typeof(T))
34+
where T : IClassConstructor, new()
1835
{
19-
public override Type ClassConstructorType { get; } = typeof(T);
20-
}
36+
public override Type ClassConstructorType { get; set; } = typeof(T);
37+
}

TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet2_0.verified.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ namespace TUnit.Core
7777
public static TUnit.Core.AsyncEvent<TEventArgs> operator +(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7878
public static TUnit.Core.AsyncEvent<TEventArgs>? operator -(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7979
}
80+
public abstract class BaseClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
81+
{
82+
public abstract System.Type ClassConstructorType { get; set; }
83+
}
8084
[System.AttributeUsage(System.AttributeTargets.Method)]
8185
public abstract class BaseTestAttribute : TUnit.Core.TUnitAttribute
8286
{
@@ -116,16 +120,18 @@ namespace TUnit.Core
116120
public int Order { get; }
117121
public void OnTestDiscovery(TUnit.Core.DiscoveredTestContext discoveredTestContext) { }
118122
}
119-
public abstract class ClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
123+
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124+
public class ClassConstructorAttribute : TUnit.Core.BaseClassConstructorAttribute
120125
{
121-
public abstract System.Type ClassConstructorType { get; }
126+
public ClassConstructorAttribute(System.Type classConstructorType) { }
127+
public override System.Type ClassConstructorType { get; set; }
122128
}
123129
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124130
public sealed class ClassConstructorAttribute<T> : TUnit.Core.ClassConstructorAttribute
125131
where T : TUnit.Core.Interfaces.IClassConstructor, new ()
126132
{
127133
public ClassConstructorAttribute() { }
128-
public override System.Type ClassConstructorType { get; }
134+
public override System.Type ClassConstructorType { get; set; }
129135
}
130136
public class ClassConstructorMetadata : System.IEquatable<TUnit.Core.ClassConstructorMetadata>
131137
{

TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ namespace TUnit.Core
7777
public static TUnit.Core.AsyncEvent<TEventArgs> operator +(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7878
public static TUnit.Core.AsyncEvent<TEventArgs>? operator -(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7979
}
80+
public abstract class BaseClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
81+
{
82+
public abstract System.Type ClassConstructorType { get; set; }
83+
}
8084
[System.AttributeUsage(System.AttributeTargets.Method)]
8185
public abstract class BaseTestAttribute : TUnit.Core.TUnitAttribute
8286
{
@@ -116,16 +120,18 @@ namespace TUnit.Core
116120
public int Order { get; }
117121
public void OnTestDiscovery(TUnit.Core.DiscoveredTestContext discoveredTestContext) { }
118122
}
119-
public abstract class ClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
123+
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124+
public class ClassConstructorAttribute : TUnit.Core.BaseClassConstructorAttribute
120125
{
121-
public abstract System.Type ClassConstructorType { get; }
126+
public ClassConstructorAttribute(System.Type classConstructorType) { }
127+
public override System.Type ClassConstructorType { get; set; }
122128
}
123129
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124130
public sealed class ClassConstructorAttribute<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T> : TUnit.Core.ClassConstructorAttribute
125131
where T : TUnit.Core.Interfaces.IClassConstructor, new ()
126132
{
127133
public ClassConstructorAttribute() { }
128-
public override System.Type ClassConstructorType { get; }
134+
public override System.Type ClassConstructorType { get; set; }
129135
}
130136
public class ClassConstructorMetadata : System.IEquatable<TUnit.Core.ClassConstructorMetadata>
131137
{

TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ namespace TUnit.Core
7777
public static TUnit.Core.AsyncEvent<TEventArgs> operator +(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7878
public static TUnit.Core.AsyncEvent<TEventArgs>? operator -(TUnit.Core.AsyncEvent<TEventArgs>? e, System.Func<object, TEventArgs, System.Threading.Tasks.Task> callback) { }
7979
}
80+
public abstract class BaseClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
81+
{
82+
public abstract System.Type ClassConstructorType { get; set; }
83+
}
8084
[System.AttributeUsage(System.AttributeTargets.Method)]
8185
public abstract class BaseTestAttribute : TUnit.Core.TUnitAttribute
8286
{
@@ -116,16 +120,18 @@ namespace TUnit.Core
116120
public int Order { get; }
117121
public void OnTestDiscovery(TUnit.Core.DiscoveredTestContext discoveredTestContext) { }
118122
}
119-
public abstract class ClassConstructorAttribute : TUnit.Core.TUnitAttribute, TUnit.Core.IDataAttribute
123+
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124+
public class ClassConstructorAttribute : TUnit.Core.BaseClassConstructorAttribute
120125
{
121-
public abstract System.Type ClassConstructorType { get; }
126+
public ClassConstructorAttribute(System.Type classConstructorType) { }
127+
public override System.Type ClassConstructorType { get; set; }
122128
}
123129
[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class)]
124130
public sealed class ClassConstructorAttribute<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] T> : TUnit.Core.ClassConstructorAttribute
125131
where T : TUnit.Core.Interfaces.IClassConstructor, new ()
126132
{
127133
public ClassConstructorAttribute() { }
128-
public override System.Type ClassConstructorType { get; }
134+
public override System.Type ClassConstructorType { get; set; }
129135
}
130136
public class ClassConstructorMetadata : System.IEquatable<TUnit.Core.ClassConstructorMetadata>
131137
{
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TUnit.TestProject
2+
3+
open TUnit.Core
4+
5+
[<ClassConstructor(typeof<DependencyInjectionClassConstructor>)>]
6+
type ClassConstructorTest(dummyReferenceTypeClass: DummyReferenceTypeClass) =
7+
8+
member _.DummyReferenceTypeClass = dummyReferenceTypeClass
9+
10+
[<Test>]
11+
member _.Test() = ()
12+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace TUnit.TestProject.FSharp
2+
3+
open System
4+
open Microsoft.Extensions.DependencyInjection
5+
open TUnit
6+
open TUnit.TestProject
7+
open TUnit.Core
8+
9+
[<ClassConstructor(typeof<DependencyInjectionClassConstructor>)>]
10+
[<NotInParallel>]
11+
type ClassConstructorWithEnumerableTest(services: IServiceProvider) =
12+
let mutable isDisposed = false
13+
14+
[<Before(HookType.Test)>]
15+
member _.Setup() =
16+
if isDisposed then
17+
raise (ObjectDisposedException(nameof(ClassConstructorWithEnumerableTest)))
18+
19+
[<Test>]
20+
[<MethodDataSource("GetValues")>]
21+
member _.DoSomething(value: int) =
22+
ActivatorUtilities.GetServiceOrCreateInstance<DummyReferenceTypeClass>(services) |> ignore
23+
24+
static member GetValues() : seq<int> = seq { yield 1; yield 2; yield 3; yield 4 }
25+
26+
interface IDisposable with
27+
member _.Dispose() =
28+
isDisposed <- true
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace TUnit.TestProject
2+
3+
open System
4+
open System.Threading.Tasks
5+
open Microsoft.Extensions.DependencyInjection
6+
open TUnit.Core.Interfaces
7+
8+
type DependencyInjectionClassConstructor() =
9+
let serviceProvider: IServiceProvider =
10+
ServiceCollection()
11+
.AddTransient<DummyReferenceTypeClass>()
12+
.BuildServiceProvider()
13+
let mutable scope : AsyncServiceScope option = None
14+
15+
interface IClassConstructor with
16+
member _.Create(typ, _) =
17+
if scope.IsNone then
18+
scope <- Some(serviceProvider.CreateAsyncScope())
19+
ActivatorUtilities.GetServiceOrCreateInstance(scope.Value.ServiceProvider, typ)
20+
21+
interface ITestEndEventReceiver with
22+
member _.OnTestEnd(_testContext) =
23+
match scope with
24+
| Some s -> s.DisposeAsync()
25+
| None -> ValueTask()
26+
member _.Order = 0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace TUnit.TestProject
2+
3+
type DummyReferenceTypeClass() = class end
4+

TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@
1313
</ItemGroup>
1414

1515
<ItemGroup>
16+
<Compile Include="DummyReferenceTypeClass.fs" />
17+
<Compile Include="DependencyInjectionClassConstructor.fs" />
18+
<Compile Include="ClassConstructorTest.fs" />
19+
<Compile Include="ClassConstructorWithEnumerableTest.fs" />
1620
<Compile Include="ClassDataSourceDrivenTests.fs" />
1721
<Compile Include="Tests.fs" />
1822
</ItemGroup>
1923

2024
<ItemGroup>
2125
<PackageReference Include="FSharp.Core" />
26+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
2227
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" />
2328
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" />
2429
</ItemGroup>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Imports TUnit.Core
2+
3+
<ClassConstructor(GetType(DependencyInjectionClassConstructor))>
4+
Public Class ClassConstructorTest
5+
6+
Public Sub New(dummyReferenceTypeClass As DummyReferenceTypeClass)
7+
Me.DummyReferenceTypeClass = dummyReferenceTypeClass
8+
End Sub
9+
10+
Public ReadOnly Property DummyReferenceTypeClass As DummyReferenceTypeClass
11+
12+
<Test>
13+
Public Sub Test()
14+
' Test logic here
15+
End Sub
16+
17+
End Class

0 commit comments

Comments
 (0)