Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="10.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,59 +1,106 @@
using Moq;

namespace UsingStaticInCSharp.Tests;

public class UsingStaticUnitTest
{
private static string CaptureOutput(Action invoke)
{
var original = Console.Out;
using var writer = new StringWriter();
Console.SetOut(writer);
try
{
invoke();
}
finally
{
Console.SetOut(original);
}

return writer.ToString();
}

[Fact]
public void GivenAStaticMethodFromClassA_WhenCalledByUsingStaticFeature_ThenItRuns()
{
var output = CaptureOutput(() => new MethodsAndProperties.Caller().Invoke());

Assert.Contains("MethodsAndProperties.ClassA.MethodA() called", output);
Assert.Contains("MethodsAndProperties.ClassA.MethodB() called", output);
}

[Fact]
public void GivenAnEnum_WhenItemsAreUsedByUsingStaticFeature_ThenTheyResolve()
{
var output = CaptureOutput(() => new Enums.Caller().Invoke());

Assert.Contains("The enum items are User, Admin", output);
}

[Fact]
public void GivenStaticConstants_WhenUsedByUsingStaticFeature_ThenTheyResolve()
{
var output = CaptureOutput(() => new Constants.Caller().Invoke());

Assert.Contains("Pending, InProgress, Completed", output);
}

[Fact]
public void GivenANestedClass_WhenCalledByUsingStaticFeature_ThenItRuns()
{
var output = CaptureOutput(() => new NestedTypeMembers.Caller().Invoke());

Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodA() called", output);
Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodB() called", output);
}

[Fact]
public void GivenAStaticConstant_WhenCalledByUsingStaticFeature_ShouldBeInvoked()
public void GivenTheOuterClass_WhenImportedByUsingStatic_ThenTheNestedClassNeedsNoPrefix()
{
var mock = new Mock<Constants.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new NestedTypeMembers.OuterTypeCaller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodA() called", output);
Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodB() called", output);
}

[Fact]
public void GivenANestedClassFromSampleClassOne_WhenCalledByUsingStaticFeature_ShouldBeInvoked()
public void GivenAnExtensionMethodInDifferentNamespace_WhenImportedByUsingStatic_ThenItIsFound()
{
var mock = new Mock<NestedTypeMembers.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new ExtensionMethods.Caller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("The sum is 3", output);
}

[Fact]
public void GivenAStaticMethodFromClassA_WhenCalledByUsingStaticFeature_ShouldBeInvoked()
public void GivenADerivedClass_WhenItsOwnStaticMethodIsCalledByUsingStatic_ThenItRuns()
{
var mock = new Mock<MethodsAndProperties.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new BaseClassMembers.Caller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("BaseClassMembers.ClassB.MethodB() called", output);
}

[Fact]
public void GivenAAmbiguityMethodFromClassAAndClassB_WhenCalledByItsClassName_ShouldBeInvoked()
public void GivenTwoClassesWithTheSameMethod_WhenCalledByClassName_ThenBothRun()
{
var mock = new Mock<Ambiguity.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new Ambiguity.Caller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("Ambiguity.ClassA.Method() called", output);
Assert.Contains("Ambiguity.ClassB.Method() called", output);
}

[Fact]
public void GivenAEnum_WhenCalledByUsingStaticFeature_ShouldBeInvoked()
public void GivenAGlobalUsingStatic_WhenMathMembersAreCalledWithoutTypeName_ThenTheyResolve()
{
var mock = new Mock<Enums.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new GlobalUsingStatic.Caller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("The hypotenuse is 5", output);
Assert.Contains("The best score is 9", output);
}

[Fact]
public void GivenAnExtensionMethodInDifferentNamespace_WhenCalledByUsingStaticFeature_ShouldBeInvoked()
public void GivenAMemberWithTheSameName_WhenCalledUnqualified_ThenTheEnclosingTypeWins()
{
var mock = new Mock<ExtensionMethods.Caller>();
mock.Object.Invoke();
var output = CaptureOutput(() => new MemberPrecedence.Caller().Invoke());

mock.Verify(x => x.Invoke());
Assert.Contains("Describe() returned Caller.Describe()", output);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ public class Caller
{
public virtual void Invoke()
{
Console.WriteLine("The contants are {0}, {1}, {2}", Pending, InProgress, Completed);
Console.WriteLine("The constants are {0}, {1}, {2}", Pending, InProgress, Completed);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using static UsingStaticInCSharp.GlobalUsingStatic.Scores;

namespace UsingStaticInCSharp.GlobalUsingStatic;
public class Caller
{
public virtual void Invoke()
{
var hypotenuse = Sqrt(Pow(3, 2) + Pow(4, 2));
Console.WriteLine("The hypotenuse is {0}", hypotenuse);

var best = Scores.Max(3, 9);
Console.WriteLine("The best score is {0}", best);

// Error CS0121 The call is ambiguous
// between the following methods or properties:
// 'System.Math.Max(int, int)' and 'UsingStaticInCSharp.GlobalUsingStatic.Scores.Max(int, int)'
// var best = Max(3, 9);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using static System.Math;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace UsingStaticInCSharp.GlobalUsingStatic;
public static class Scores
{
public static int Max(int first, int second) => first > second ? first : second;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using static UsingStaticInCSharp.MemberPrecedence.ClassA;

namespace UsingStaticInCSharp.MemberPrecedence;
public class Caller
{
public virtual void Invoke()
{
Console.WriteLine("Describe() returned {0}", Describe());
}

private static string Describe() => "Caller.Describe()";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace UsingStaticInCSharp.MemberPrecedence;
public static class ClassA
{
public static string Describe() => "ClassA.Describe()";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public class Caller
{
public virtual void Invoke()
{
MethodA();
MethodB();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
namespace UsingStaticInCSharp.NestedTypeMembers;
public static class ClassA
public class ClassA
{
public static class ClassB
public class ClassB
{
public static void MethodA()
{
Console.WriteLine("NestedTypeMembers.ClassA.ClassB.MethodA() called");
}

public static void MethodB()
{
Console.WriteLine("NestedTypeMembers.ClassA.ClassB.MethodB() called");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using static UsingStaticInCSharp.NestedTypeMembers.ClassA;

namespace UsingStaticInCSharp.NestedTypeMembers;
public class OuterTypeCaller
{
public virtual void Invoke()
{
ClassB.MethodA();
ClassB.MethodB();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ static void Main(string[] args)
new Enums.Caller().Invoke();
new Constants.Caller().Invoke();
new NestedTypeMembers.Caller().Invoke();
new NestedTypeMembers.OuterTypeCaller().Invoke();
new ExtensionMethods.Caller().Invoke();
new BaseClassMembers.Caller().Invoke();
new Ambiguity.Caller().Invoke();
new GlobalUsingStatic.Caller().Invoke();
new MemberPrecedence.Caller().Invoke();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Loading