With R3 2023 (2023.3.1011.155) JustMock introduces a new functionality that might lead to a huge performance drop and event to unexpected failures. Currently, the issue could be suppressed by setting up an environment variable JUSTMOCK_NEWOBJ_INTERCEPTION_ON_OVERWRITE_ENABLED to 0 (the default value is 1), but a more reliable and independent solution should be found.
We're using this DevOps task in our pipeline, however since yesterday we get the following warning:
##[warning]Task 'Telerik JustMock VSTest v.2' version 2 (JustMockVSTest@2) is dependent on a Node version (6) that is end-of-life. Contact the extension owner for an updated version of the task. Task maintainers should review Node upgrade guidance: https://aka.ms/node-runner-guidance
We're running it using a build agent hosted at the Azure DevOps cloud.
if you use the C# using declaration and have JustMock advanced (elevated) mode enabled, the runtime will throw an InvalidProgramException.
Find below the sample code that demonstrates the issue:
public class TestClass : IDisposable
{
public void Dispose()
{
}
}
[TestClass]
public class Fixture
{
public interface ITest { }
[TestMethod]
public async Task Test()
{
ITest mock = Mock.Create<ITest>();
using TestClass test = new();
}
}
Having the simple class
public class MyClass
{
public event Func<EventArgs, Task>? MyEventAsync;
}
and the test that tries to rise the declared event
[TestMethod]
public void TestMethod1()
{
var mockClass = Mock.Create<MyClass>(Behavior.Strict);
mockClass.MyEventAsync += (args) => Task.CompletedTask;
Mock.Raise(() => mockClass.MyEventAsync += null, EventArgs.Empty);
}
Execution triggers the following error:
Telerik.JustMock.Core.MockException : Event signature System.Threading.Tasks.Task OnMyEventAsync(System.EventArgs) is incompatible with argument types (Castle.Proxies.ExternalMockMixinProxy, System.EventArgs)
which is kind of unexpected since the supplied arguments are matching to the event's signature.
The issue is about interoperability between JustMock and AutoFixture. The unit test run can be 90% faster if all the fixtures are created before the JustMock arrangements.
Here is a sample code that figures out the issue:
[Fact]
public void Slow
{
var fixture = new Fixture():
var items1 = fixture.Create<List<Item>>();
Nock.Arrange(() => ItemsRepository.GetItems1()).Returns(items1);
var items2 = fixture.Create<List<Item>>();
Nock.Arrange(() => ItemsRepository.GetItems2()).Returns(items2);
var items3 = fixture.Create<List<Item>>();
Nock.Arrange(() => ItemsRepository.GetItems3()).Returns(items3);
var items4 = fixture.Create<List<Item>>();
Nock.Arrange(() => ItemsRepository.GetItems4()).Returns(items4);
}
[Fact]
public void Fast()
{
var fixture = new Fixture():
var items1 = fixture.Create<List<Item>>();
var items2 = fixture.Create<List<Item>>();
var items3 = fixture.Create<List<Item>>();
var items4 = fixture.Create<List<Item>>();
Nock.Arrange(() => ItemsRepository.GetItems1()).Returns(items1);
Nock.Arrange(() => ItemsRepository.GetItems2()).Returns(items2);
Nock.Arrange(() => ItemsRepository.GetItems3()).Returns(items3);
Nock.Arrange(() => ItemsRepository.GetItems4()).Returns(items4);
}
The test duration should not be dependent on the exact implementation.
Considering the sample class
using Azure.Messaging.ServiceBus;
public class Class2
{
private static ServiceBusSender messageToTopicSender;
private static string topicName;
public static void SetRequestTopicClient(string serviceBusConnectionString, string topName)
{
topicName = topName;
ServiceBusClient serviceBusClient = new ServiceBusClient(serviceBusConnectionString);
messageToTopicSender = serviceBusClient.CreateSender(topicName);
}
}
and the following tests
[TestClass]
public class Class1Test
{
[TestInitialize]
public void SetUp()
{
Mock.Arrange(() => Class2.SetRequestTopicClient("", "")).DoNothing();
}
[TestMethod]
public void TestA()
{
Class2.SetRequestTopicClient("", "");
}
}
[TestClass]
public class Class2Test
{
static ServiceBusClient serviceBusClient = Mock.Create<ServiceBusClient>();
ServiceBusSender messageToTopicSender = Mock.Create<ServiceBusSender>();
[TestInitialize]
public void SetUp()
{
Mock.Arrange(() => new ServiceBusClient("conStr")).Returns(serviceBusClient);
Mock.Arrange(() => serviceBusClient.CreateSender("myTopic")).Returns(messageToTopicSender);
}
[TestMethod]
public void TestB()
{
Class2.SetRequestTopicClient("conStr", "myTopic");
}
}
Executing the tests in order TestA -> TestB results in failed TestB, but changing the order or runining them standalone succeeds.The outcome of the tests should not be dependent of the execution order.
A unit test run against a simple class using EntityFramework never completes, here's the code:
public class DbContext1 : DbContext
{
public DbContext1(string connectionString)
{
}
}
public class Program
{
private static readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
public async Task Run()
{
await _lock.WaitAsync();
try
{
await InsertDbRow();
}
finally
{
_lock.Release();
}
}
private static async Task InsertDbRow()
{
await RetryWrapperAsync(async () =>
{
using DbContext1 dbContext = new DbContext1("con str");
await dbContext.SaveChangesAsync();
});
}
public static async Task RetryWrapperAsync(Func<Task> operation)
{
for (int i = 0; i < 3; i++)
{
try
{
await operation();
break;
}
catch (Exception)
{
await Task.Delay(100);
}
};
}
}
[TestClass]
public class ProgramTest
{
private readonly DbContext1 mockContext1 = Mock.Create<DbContext1>();
[TestInitialize]
public void SetUp()
{
Mock.Arrange(() => new DbContext1("con str")).Returns(mockContext1);
}
[TestMethod]
public async Task TestMethod()
{
// Arrange
Program program = new Program();
// Act
await program.Run(); // <-- at this point the test hangs
}
}
Adding do-nothing arrangement on mockContext.SaveChanges fixes the hang, but the expectation is that mock will handle this case by default and there is no need to be explicitly arranged.
Dear Telerik team,
It is nice to have a way to generate mocks.
But it is annoying to have lots of those messages for references in XML comments. I had to turn the feature off. Which might be the case for other customers too.
Maybe you want to have a look into it.
I am unable to mock interfaces that contain a method with an `in` parameter. When running the following code snippet, the result is an exception:
Message:
Test method Example.UnitTests.UnitTest.TestMethod threw exception:
Telerik.JustMock.Core.MockException: Abstract type 'Example.UnitTests.InParamExample' is not accessible for inheritance.
Stack Trace:
MocksRepository.Create(Type type, MockCreationSettings settings)
<>c__38`1.<Create>b__38_0()
ProfilerInterceptor.GuardInternal[T](Func`1 guardedAction)
UnitTest.TestMethod() line 23
namespace Example.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Telerik.JustMock;
public interface ParamExample
{
void Foo(int param);
}
public interface InParamExample
{
void Foo(in int param);
}
[TestClass]
public class UnitTest
{
[TestMethod]
public void TestMethod()
{
var mockedParamExample = Mock.Create<ParamExample>();
var mockedInParamExample = Mock.Create<InParamExample>();
}
}
}
Mock.Create<IPool>() fails with
Telerik.JustMock.Core.MockException : Abstract type 'IPool' is not accessible for inheritance.
In Telerik.JustMock.Core.MocksRepository.Create(Type type, MockCreationSettings settings)
In Telerik.JustMock.Mock.<>c__39`1.<Create>b__39_0()
In Telerik.JustMock.Core.ProfilerInterceptor.GuardInternal[T](Func`1 guardedAction)
when trying to create a mock object from
public interface IPool
{
object GetItem(in Struct a, out Class b);
}
The following code snippet causes a hang in the test execution while being debugged:
Mock.SetupStatic(typeof(TimeSpan), Behavior.CallOriginal, StaticConstructor.NonMocked);
Mock.Arrange(() => TimeSpan.FromSeconds(15)).Returns(TimeSpan.MinValue);
The issue can be temporary solved by disabling the DebugWindow via JustMock extension menu.
Hello
I generate a syntax tree which I will format with Formatter.Format() from the package Microsoft.CodeAnalysis.CSharp.Workspaces 4.4.0 and .NET 6. A test exists where the formatter is used but when the JustMock profiler is enabled an InvalidProgramException is thrown. When the profiler is disabled everything works fine. It fails on Windows and on Linux.
Message:
System.InvalidProgramException : Common Language Runtime detected an invalid program.
Stack Trace:
ContextIntervalTree`2.ctor(TIntrospector& introspector)
FormattingContext.ctor(AbstractFormatEngine engine, TokenStream tokenStream)
AbstractFormatEngine.CreateFormattingContext(TokenStream tokenStream, CancellationToken cancellationToken)
AbstractFormatEngine.Format(CancellationToken cancellationToken)
CSharpSyntaxFormatting.Format(SyntaxNode node, SyntaxFormattingOptions options, IEnumerable`1 formattingRules, SyntaxToken startToken, SyntaxToken endToken, CancellationToken cancellationToken)
AbstractSyntaxFormatting.GetFormattingResult(SyntaxNode node, IEnumerable`1 spans, SyntaxFormattingOptions options, IEnumerable`1 rules, CancellationToken cancellationToken)
Formatter.GetFormattingResult(SyntaxNode node, IEnumerable`1 spans, Workspace workspace, OptionSet options, IEnumerable`1 rules, CancellationToken cancellationToken)
Formatter.Format(SyntaxNode node, IEnumerable`1 spans, Workspace workspace, OptionSet options, IEnumerable`1 rules, CancellationToken cancellationToken)
Formatter.Format(SyntaxNode node, Workspace workspace, OptionSet options, CancellationToken cancellationToken)
UnitTest1.Test1() line 23
You can reproduce this by writing an unit test for that (I used xUnit):
[Fact]
public void Test1()
{
var classText = @"using System; namespace TestNameSpace.Orders { public class Order
{
public Guid Id { get; set; }
}
}";
var syntaxTree = CSharpSyntaxTree.ParseText(classText);
var workspace = new AdhocWorkspace();
var formattedClassText = Formatter.Format(syntaxTree.GetRoot(), workspace).ToFullString();
var expected = @"using System;
namespace TestNameSpace.Orders
{
public class Order
{
public Guid Id { get; set; }
}
}";
Assert.Equal(expected, formattedClassText);
}
}
See attachments. We do not use the free edition.
dotnet --info
.NET SDK:
Version: 7.0.200
Commit: 534117727b
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.200\
Host:
Version: 7.0.3
Architecture: x64
Commit: 0a2bda10e8
.NET SDKs installed:
6.0.406 [C:\Program Files\dotnet\sdk]
7.0.200 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
Using elevated mocking mode (profiler enabled) with long path names for the test containers (above 260 characters) causes the following command:
dotnet test
to fail with error:
Testhost process exited with error: Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at Microsoft.VisualStudio.TestPlatform.TestHost.Program.Main(System.String[]) . Please check the diagnostic logs for more information. Test Run Aborted.
Considering the following simple test scenario:
public abstract class TestBase
{
public static TestContext TestContext { get; set; }
}
[TestClass]
public class UnitTest1 : TestBase
{
[ClassInitialize]
public static void ClassInitlialize(TestContext ctx)
{
TestContext = ctx;
}
[TestMethod]
public void TestMethod1()
{
}
}
[TestClass]
public class UnitTest2 : TestBase
{
[ClassInitialize]
public static void ClassInitlialize(TestContext ctx)
{
TestContext = ctx;
}
[TestMethod]
public void TestMethod1()
{
}
}
Attempt to run the tests above with JustMock profiler enabled fails with System.InvalidProgramException. The issue is not reproducible with MSTest.TestFramework and MSTest.TestAdapter packages prior to 3.0.x.
The issue is demonstrated with the following sample:
[Theory]
[MemberData(nameof(GetMemberDataContext))]
public void ValidParameters_Success(int param1, int param2)
{
// Arrange
Mock.SetupStatic(typeof(MyClass), Behavior.Strict, StaticConstructor.Mocked);
Mock.Arrange(() => MyClass.method1()).Returns(true);
// Act
IService service = new Service();
bool result = service.method2();
// Assert
Assert.True(result);
Mock.Assert(() => MyClass.method1(), Occurs.Once()); // <-- the test fails here because it reports that method invocation occurs twice
}
The issue in not observed if the code is modified in the following way, which indicates behavioral incinsistency:
[Theory]
[MemberData(nameof(GetMemberDataContext))]
public void ValidParameters_Success(int param1, int param2)
{
// Arrange
Mock.SetupStatic(typeof(MyClass), Behavior.Strict, StaticConstructor.Mocked);
Mock.Arrange(() => MyClass.method1()).Returns(true).OccursOnce();
// Act
IService service = new Service();
bool result = service.method2();
// Assert
Assert.True(result);
Mock.Assert<MyClass>();
}
There are older releases with a version of 1.0.0.4 for the Telerik.JustMock.Console.exe and with the R3 2022 release, the version is 1.0.0.3.
Referencing the nuget Microsoft.ApplicationInsights.AspNetCore V2.20.0 in the project that is tested leads to the VS 2019 code coverage failing to produce the report. Here are the steps to reproduce:
1. Create a project from the template ASP.NET Core Web API targeting .NET 5
2. Add a reference to the nuget package Microsoft.ApplicationInsights.AspNetCore V2.20.0
3. Create a unit test project from the C# JustMock Test Project (.NET Core) template.
4. Run the VS code coverage.
Expected result: the code coverage report is produced.
Actual result: there is no code coverage report