From e46bf2d86dac1960dd52f47e93e183015f8e799d Mon Sep 17 00:00:00 2001 From: MladenStankov Date: Mon, 31 Aug 2026 14:11:11 +0300 Subject: [PATCH 1/3] JM-260: Add Mock.SetupFuture() API and core infrastructure - Add futureMixinDatabase field to MocksRepository - Add InterceptFuture method mirroring InterceptStatics - Modify GetMockMixin to check futureMixinDatabase for instance calls - Add futureMixinDatabase.Clear() in Reset() for test isolation - Create Mock.SetupFuture.cs with four overloads gated by #if !LITE_EDITION Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Telerik.JustMock/Core/MocksRepository.cs | 36 ++++++++ Telerik.JustMock/Mock.SetupFuture.cs | 110 +++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 Telerik.JustMock/Mock.SetupFuture.cs diff --git a/Telerik.JustMock/Core/MocksRepository.cs b/Telerik.JustMock/Core/MocksRepository.cs index 9233e56a..9a74b943 100644 --- a/Telerik.JustMock/Core/MocksRepository.cs +++ b/Telerik.JustMock/Core/MocksRepository.cs @@ -63,6 +63,7 @@ public sealed class MocksRepository private readonly int repositoryId; private readonly Thread creatingThread; private readonly Dictionary staticMixinDatabase = new Dictionary(); + private readonly Dictionary futureMixinDatabase = new Dictionary(); private readonly Dictionary arrangementTreeRoots = new Dictionary(); private readonly Dictionary invocationTreeRoots = new Dictionary(); private readonly Dictionary, object> valueStore = new Dictionary, object>(); @@ -274,6 +275,17 @@ internal static IMockMixin GetMockMixin(object obj, Type objType) if (obj != null) { asMixin = GetMixinFromExternalDatabase(obj, objType); + + // Check future mixin database for instance calls where no explicit mock exists + if (asMixin == null) + { + MocksRepository repo = MockingContext.ResolveRepository(UnresolvedContextBehavior.CreateNewContextual); + if (repo != null) + { + lock (repo.futureMixinDatabase) + repo.futureMixinDatabase.TryGetValue(objType, out asMixin); + } + } } else if (objType != null) { @@ -431,6 +443,7 @@ internal void Reset() this.arrangedTypes.Clear(); this.staticMixinDatabase.Clear(); + this.futureMixinDatabase.Clear(); foreach (var method in this.globallyInterceptedMethods) { @@ -798,6 +811,29 @@ internal void InterceptStatics(Type type, MockCreationSettings settings, bool mo this.EnableInterception(type); } + internal void InterceptFuture(Type type, MockCreationSettings settings) + { + if (!ProfilerInterceptor.IsProfilerAttached) + ProfilerInterceptor.ThrowElevatedMockingException(type); + + if (!settings.FallbackBehaviors.OfType().Any()) + ProfilerInterceptor.CheckIfSafeToInterceptWholesale(type); + + var mockMixin = (IMockMixin)Create(typeof(ExternalMockMixin), + new MockCreationSettings + { + Mixins = settings.Mixins, + SupplementaryBehaviors = settings.SupplementaryBehaviors, + FallbackBehaviors = settings.FallbackBehaviors, + MustCreateProxy = true, + }); + + lock (futureMixinDatabase) + futureMixinDatabase[type] = mockMixin; + + this.EnableInterception(type); + } + private MockMixin CreateMockMixin(Type declaringType, MockCreationSettings settings) { return CreateMockMixin(declaringType, settings, settings.MockConstructorCall); diff --git a/Telerik.JustMock/Mock.SetupFuture.cs b/Telerik.JustMock/Mock.SetupFuture.cs new file mode 100644 index 00000000..a0a87ffd --- /dev/null +++ b/Telerik.JustMock/Mock.SetupFuture.cs @@ -0,0 +1,110 @@ +/* + JustMock Lite + Copyright © 2010-2015,2018,2026 Progress Software Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using System; +using Telerik.JustMock.Core; +using Telerik.JustMock.Core.Context; + +namespace Telerik.JustMock +{ + public partial class Mock + { +#if !LITE_EDITION + /// + /// Sets up future mocking for all instance members of type + /// with behavior. + /// All future instances of created during the test will have + /// their instance methods and properties intercepted with the default behavior. + /// + /// + /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. + /// Constructors are not intercepted; use Mock.Arrange(() => new T()).DoNothing() for constructor mocking. + /// Per-method arrangements made after this call take precedence over the class-level default. + /// + /// Target type to future-mock. + public static void SetupFuture() + { + ProfilerInterceptor.GuardInternal(() => + { + MockCreationSettings settings = MockCreationSettings.GetSettings(); + MockingContext.CurrentRepository.InterceptFuture(typeof(T), settings); + }); + } + + /// + /// Sets up future mocking for all instance members of type + /// with the specified behavior. + /// + /// + /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. + /// Constructors are not intercepted; use Mock.Arrange(() => new T()).DoNothing() for constructor mocking. + /// Per-method arrangements made after this call take precedence over the class-level default. + /// + /// Target type to future-mock. + /// + /// Specifies behavior of the mock. Default is . + /// + public static void SetupFuture(Behavior behavior) + { + ProfilerInterceptor.GuardInternal(() => + { + MockCreationSettings settings = MockCreationSettings.GetSettings(behavior); + MockingContext.CurrentRepository.InterceptFuture(typeof(T), settings); + }); + } + + /// + /// Sets up future mocking for all instance members of the specified type + /// with behavior. + /// + /// Target type to future-mock. + /// Thrown when is null. + public static void SetupFuture(Type type) + { + ProfilerInterceptor.GuardInternal(() => + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + MockCreationSettings settings = MockCreationSettings.GetSettings(); + MockingContext.CurrentRepository.InterceptFuture(type, settings); + }); + } + + /// + /// Sets up future mocking for all instance members of the specified type + /// with the specified behavior. + /// + /// Target type to future-mock. + /// + /// Specifies behavior of the mock. Default is . + /// + /// Thrown when is null. + public static void SetupFuture(Type type, Behavior behavior) + { + ProfilerInterceptor.GuardInternal(() => + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + MockCreationSettings settings = MockCreationSettings.GetSettings(behavior); + MockingContext.CurrentRepository.InterceptFuture(type, settings); + }); + } +#endif + } +} From 871ae4eaf25471b011102b3b306a731c12fbe2fa Mon Sep 17 00:00:00 2001 From: MladenStankov Date: Mon, 31 Aug 2026 15:00:14 +0300 Subject: [PATCH 2/3] =?UTF-8?q?JM-260:=20Fix=20SetupFuture=20XML=20doc=20?= =?UTF-8?q?=E2=80=94=20constructors=20are=20intercepted=20by=20wholesale?= =?UTF-8?q?=20interception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrects the misleading 'Constructors are not intercepted' remark on all four SetupFuture overloads. SetupFuture uses EnableInterception which applies wholesale interception including constructors, consistent with SetupStatic. - Update remarks on SetupFuture() and SetupFuture(Behavior) to accurately describe constructor interception behavior and guidance to use CallOriginal if constructor execution is required. - Add to the Type overloads (SetupFuture(Type) and SetupFuture(Type, Behavior)) which previously had no remarks section at all. --- Telerik.JustMock/Mock.SetupFuture.cs | 29 ++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Telerik.JustMock/Mock.SetupFuture.cs b/Telerik.JustMock/Mock.SetupFuture.cs index a0a87ffd..8cf64609 100644 --- a/Telerik.JustMock/Mock.SetupFuture.cs +++ b/Telerik.JustMock/Mock.SetupFuture.cs @@ -32,7 +32,12 @@ public partial class Mock /// /// /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. - /// Constructors are not intercepted; use Mock.Arrange(() => new T()).DoNothing() for constructor mocking. + /// Like , this call enables wholesale interception of all members + /// of , including constructors. When using the default + /// behavior, constructor bodies do not execute — fields + /// will not be initialized by the constructor. Use if + /// constructor execution is required, or arrange the constructor explicitly with + /// Mock.Arrange(() => new T()).CallOriginal(). /// Per-method arrangements made after this call take precedence over the class-level default. /// /// Target type to future-mock. @@ -51,7 +56,11 @@ public static void SetupFuture() /// /// /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. - /// Constructors are not intercepted; use Mock.Arrange(() => new T()).DoNothing() for constructor mocking. + /// Like , this call enables wholesale interception of all members + /// of , including constructors. When using + /// or behavior, constructor bodies do not execute — fields will not be + /// initialized by the constructor. Use if constructor execution + /// is required, or arrange the constructor explicitly with Mock.Arrange(() => new T()).CallOriginal(). /// Per-method arrangements made after this call take precedence over the class-level default. /// /// Target type to future-mock. @@ -71,6 +80,14 @@ public static void SetupFuture(Behavior behavior) /// Sets up future mocking for all instance members of the specified type /// with behavior. /// + /// + /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. + /// Like , this call enables wholesale interception of all members + /// of , including constructors. Constructor bodies do not execute under the + /// default behavior. Use + /// if constructor execution is required. + /// Per-method arrangements made after this call take precedence over the class-level default. + /// /// Target type to future-mock. /// Thrown when is null. public static void SetupFuture(Type type) @@ -89,6 +106,14 @@ public static void SetupFuture(Type type) /// Sets up future mocking for all instance members of the specified type /// with the specified behavior. /// + /// + /// This method requires the JustMock profiler (CodeWeaver). It is not available in JustMock Lite. + /// Like , this call enables wholesale interception of all members + /// of , including constructors. Constructor bodies do not execute under + /// or behavior. Use + /// if constructor execution is required. + /// Per-method arrangements made after this call take precedence over the class-level default. + /// /// Target type to future-mock. /// /// Specifies behavior of the mock. Default is . From 6d3f1b3a5905b257677a6ac74b5d2dc108bcce3c Mon Sep 17 00:00:00 2001 From: MladenStankov Date: Mon, 31 Aug 2026 15:26:17 +0300 Subject: [PATCH 3/3] Add Nia configuration files and update .gitignore for new context --- .gitignore | 7 ++ .nia/.context.lock | 0 .nia/config/agents.toml | 64 ++++++++++++++++++ .nia/config/project.toml | 54 ++++++++++++++++ .nia/config/telemetry.toml | 9 +++ .nia/config/toolchain.toml | 129 +++++++++++++++++++++++++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 .nia/.context.lock create mode 100644 .nia/config/agents.toml create mode 100644 .nia/config/project.toml create mode 100644 .nia/config/telemetry.toml create mode 100644 .nia/config/toolchain.toml diff --git a/.gitignore b/.gitignore index 2d0f89a8..974d6fd3 100644 --- a/.gitignore +++ b/.gitignore @@ -155,3 +155,10 @@ $RECYCLE.BIN/ # Mac crap .DS_Store + +# Nia +/.nia/work +/.nia/context.toml +/.nia/logs +/.nia/.config_lock +/.nia/.config.lock \ No newline at end of file diff --git a/.nia/.context.lock b/.nia/.context.lock new file mode 100644 index 00000000..e69de29b diff --git a/.nia/config/agents.toml b/.nia/config/agents.toml new file mode 100644 index 00000000..87047e5f --- /dev/null +++ b/.nia/config/agents.toml @@ -0,0 +1,64 @@ +# Generated by: nia config init --agent github_copilot --models balanced +# Generated at: 2026-08-31T12:16:30.307061+00:00 +# Agent: github_copilot (GitHub Copilot CLI) +# Profile: balanced - Good performance at reasonable cost +# +# Model Selection Rationale: +# Model Tier Guide: +# - Default (gpt-5.4): Standard tier - balanced performance for most operations +# - issue.draft (gpt-5.5): Heavy/Reasoning tier - premium for user-facing output +# - issue.plan (gpt-5.5): Heavy/Reasoning tier - premium for strategic planning +# - issue.review (gpt-5.5): Heavy/Reasoning tier - premium for review quality +# - pr.review (gpt-5.5): Heavy/Reasoning tier - premium for PR assessment +# - pr.merge (gpt-5.5): Heavy/Reasoning tier - premium for high-risk operations + +schema_version = "1.0.0" + +[agent] +default = "github_copilot" + +[agent.github_copilot] +model = "gpt-5.4" + +[agent.github_copilot.operations] +"issue.review" = "gpt-5.5" +"issue.plan" = "gpt-5.5" +"pr.merge" = "gpt-5.5" +"pr.review" = "gpt-5.5" +"issue.draft" = "gpt-5.5" + +# ============================================================================ +# Commit Configuration (optional) +# ============================================================================ +# +# Control which commands include commit instructions in their prompts. +# By default, commands that modify code/docs include commit instructions, +# while review/analysis commands do not. +# +# Commands with commits enabled by default: +# - Code generation and refactoring (create, refactor, fix modes) +# - Documentation generation and build fixes +# - Pull request merge operations +# - Security patching +# +# Commands with commits disabled by default: +# - Review and analysis operations +# - Draft generation tasks +# - Ask/query commands +# - Security audit operations +# +# To override defaults, use the extended target/operation syntax: +# +# [agent.github_copilot.targets] +# code = { model = "gpt-4", commits = "on" } # Enable commits for all code target operations +# issue = { commits = "off" } # Disable commits for all issue target operations +# +# [agent.github_copilot.operations] +# "workflow.execute" = { commits = "on" } # Enable commits for specific operation +# "workflow.plan" = { model = "gpt-4", commits = "off" } # Disable commits with model override +# +# Values: +# - "on": Enable commit instructions for this target/operation +# - "off": Disable commit instructions for this target/operation +# +# Note: project.toml [commit].behavior = "disabled" overrides ALL settings here. diff --git a/.nia/config/project.toml b/.nia/config/project.toml new file mode 100644 index 00000000..957df1cc --- /dev/null +++ b/.nia/config/project.toml @@ -0,0 +1,54 @@ +schema_version = "1.0.0" + +[project] +name = "JustMockLite" +description = "Project description" +language = "Rust" # Change to your primary language +framework = "None" # Update with your framework (e.g., "actix-web", "axum") +testing_framework = "cargo test" +package_manager = "cargo" + +[beta_consent] +acknowledged = true +acknowledgement_date = "2026-08-31T12:12:34.189752600+00:00" +acknowledged_by = "nia" +version_at_consent = "4.4.0" +consent_phrase = "i agree" + +# Uncomment and configure for monorepo +# [monorepo] +# enabled = true +# +# [[monorepo.services]] +# name = "service-a" +# path = "services/service-a" + +# Context files and directories +# +# Files and directories listed here are always included as context for AI prompts. +# This is useful for architecture docs, coding standards, or API specifications. +# +# [[project.context]] +# type = "file" +# path = "docs/architecture.md" +# description = "System architecture overview" +# +# [[project.context]] +# type = "directory" +# path = "docs/standards/" +# description = "Coding standards and guidelines" + +# Commit behavior configuration +# +# Controls how nia handles git commits during code generation tasks. +# +# Options: +# - "enabled" (default): Include basic commit instructions in prompts +# - "tagged": Include commit instructions with nia co-author attribution +# - "disabled": Do not include any commit instructions (you handle commits manually) +# +# Note: This is a global override. To configure commit behavior per command, +# use the agents.toml file (see comments in that file for examples). +# +# [commit] +# behavior = "enabled" diff --git a/.nia/config/telemetry.toml b/.nia/config/telemetry.toml new file mode 100644 index 00000000..c2cca9e3 --- /dev/null +++ b/.nia/config/telemetry.toml @@ -0,0 +1,9 @@ +[consent] +notice_shown = true +notice_shown_date = "2026-08-31T12:12:36.494017900+00:00" +notice_shown_by = "nia" +consented = true +opted_out = false +consent_date = "2026-08-31T12:12:36.494019300+00:00" +consent_phrase = "i agree" +consented_by = "nia" diff --git a/.nia/config/toolchain.toml b/.nia/config/toolchain.toml new file mode 100644 index 00000000..b4b12740 --- /dev/null +++ b/.nia/config/toolchain.toml @@ -0,0 +1,129 @@ +# Nia toolchain configuration +# This file tells AI agents what tools are available and how to access them +# +# To switch access methods for a tool: +# 1. Comment out the current 'description' field (add # prefix to each line) +# 2. Uncomment your preferred method's description block +# 3. Update the 'method' field to match the new method +schema_version = "1.0.0" + +# Issue tracker configuration +[issue_tracker] +name = "jira" +type = "built-in" +method = "skill" # Options: "cli", "mcp", "api", "skill" (default) +description = """ +When retrieving or reading issues from JIRA, use the "{{issue_tracker_skill_name}}" skill. +This skill provides guidance on JQL queries, field navigation, authentication, +and JIRA-specific best practices including checking comments and attachments. +""" + +# [CLI Method]: +# description = """ +# JIRA for agile project management and issue tracking. +# Access via Atlassian CLI (`acli jira` command). +# The Atlassian CLI must be installed and configured separately. +# Common operations: +# - View issue: acli jira workitem view {{issue_id}} +# - Edit issue: acli jira workitem edit {{issue_id}} +# """ + +# [MCP Method]: +# description = """ +# JIRA for agile project management and issue tracking. +# Access via JIRA MCP Server (if available). +# The MCP server provides tools for managing JIRA issues, sprints, and boards. +# All authentication is handled by the MCP server configuration. +# """ + +# [API Method]: +# description = """ +# JIRA for agile project management and issue tracking. +# Access via JIRA REST API. +# +# Authentication: API token required +# - Environment variable: NIA_ISSUE_TOKEN +# - Scope: Read and write access to JIRA issues +# - Management: User-managed; set externally before running Nia +# - Security: Nia does not inject tokens into logs, traces, or prompts +# +# The Coding Agent will read this token dynamically when making API calls. +# +# Common operations: +# - List issues: GET /rest/api/2/search?jql= +# - View issue: GET /rest/api/2/issue/{{issue_id}} +# - Create issue: POST /rest/api/2/issue +# - Update issue: PUT /rest/api/2/issue/{{issue_id}} +# """ + +# Code platform configuration +[code_platform] +name = "github" +type = "built-in" +method = "skill" # Options: "cli", "mcp", "api", "skill" (default) +description = """ +When retrieving or reading pull requests from the code platform, use the "{{code_platform_skill_name}}" skill. +This skill provides guidance on PR navigation, review status, diff inspection, +and code platform best practices. +""" + +# [CLI Method]: +# description = """ +# GitHub for code hosting and collaboration. +# Access via 'gh' CLI commands. +# +# {{#if code_platform_repo_slug}}Repository: {{code_platform_repo_slug}} +# +# Common operations (repository configured — use --repo flag): +# - Create PR: gh pr create --title "..." --body "..." --repo {{code_platform_repo_slug}} +# - View PR: gh pr view {{pr_id}} --repo {{code_platform_repo_slug}} +# - List PRs: gh pr list --repo {{code_platform_repo_slug}} +# - Review PR: gh pr review {{pr_id}} --repo {{code_platform_repo_slug}} +# - Merge PR: gh pr merge {{pr_id}} --repo {{code_platform_repo_slug}} +# - View repo: gh repo view --repo {{code_platform_repo_slug}} +# {{/if}} +# {{#unless code_platform_repo_slug}}Common operations: +# - Create PR: gh pr create --title "..." --body "..." +# - View PR: gh pr view {{pr_id}} +# - List PRs: gh pr list +# - Review PR: gh pr review {{pr_id}} +# - Merge PR: gh pr merge {{pr_id}} +# - View repo: gh repo view +# {{/unless}} +# """ + +# [MCP Method]: +# description = """ +# GitHub for code hosting and collaboration. +# Access via GitHub MCP Server. +# The MCP server provides comprehensive tools for repository operations including pull requests, code reviews, branches, and commits. +# All authentication is handled by the MCP server configuration. +# """ + +# [API Method]: +# description = """ +# GitHub for code hosting and collaboration. +# Access via GitHub REST API. +# +# Authentication: API token required +# - Environment variable: NIA_CODE_TOKEN +# - Scope: Read and write access to repositories, pull requests, and code +# - Management: User-managed; set externally before running Nia +# - Security: Nia does not inject tokens into logs, traces, or prompts +# +# The Coding Agent will read this token dynamically when making API calls. +# +# Repository placeholders: {{code_platform_repo_owner}}/{{code_platform_repo_name}} +# +# Common operations: +# - List PRs: GET /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/pulls +# - View PR: GET /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/pulls/{{pr_id}} +# - Create PR: POST /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/pulls +# - Update PR: PATCH /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/pulls/{{pr_id}} +# - Merge PR: PUT /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/pulls/{{pr_id}}/merge +# - List commits: GET /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}}/commits +# - Get repo: GET /repos/{{code_platform_repo_owner}}/{{code_platform_repo_name}} +# +# Note: When repository placeholders are empty (not configured), use auto-detected repository information from Git remote. +# """ +