Skip to content

Commit

Permalink
Documenting the ADR work that has been done
Browse files Browse the repository at this point in the history
  • Loading branch information
oswaldsql committed Nov 3, 2024
1 parent 07e0083 commit 2320298
Show file tree
Hide file tree
Showing 18 changed files with 487 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ MiniMock offers a _minimalistic_ approach to mocking in .NET. It is designed to

MiniMock is __extremely strict__, requiring you to specify all features you want to mock. This is by design to make sure you are aware of what you are mocking. Unmocked features will throw an exception if used.

[View the documentation here](https://oswaldsql.github.io/MiniMock/)

## Table of Contents
- [Simple Example](#simple-example)
- [Key Feature Summary](#key-feature-summary)
Expand Down
22 changes: 22 additions & 0 deletions docs/ADR/CreatingMocks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Decision on How to Create Mocks

## Context

In the MiniMock framework, there is a need to establish a standardized approach for creating mocks. A consistent and efficient method for creating mocks will enhance the usability and maintainability of the framework.

## Decision

Mocks will be created using a mock factory. The mock factory will provide a centralized and consistent way to create and configure mocks, ensuring that all mocks are created following the same process and standards.

## Consequences

### Positive:

- **Consistency**: Ensures that all mocks are created in a consistent manner.
- **Centralization**: Provides a single point of control for mock creation, making it easier to manage and update.
- **Ease of Use**: Simplifies the process of creating mocks for developers.

### Negative:

- **Complexity**: Introduces an additional layer of abstraction, which may add some complexity to the framework.
- **Maintenance**: Requires ongoing maintenance to ensure the mock factory remains up-to-date with any changes to the framework.
24 changes: 24 additions & 0 deletions docs/ADR/DoWeNeedANewMockingFramework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Need for a New Mocking Framework

## Context

Existing mocking frameworks in the .NET ecosystem often come with clunky APIs and external dependencies that can complicate the development process. These frameworks may offer extensive features, but they can also introduce unnecessary complexity and bloat, making them less suitable for projects that prioritize simplicity and minimalism.

## Decision

We will develop a new mocking framework, MiniMock, that focuses on providing a minimalistic and straightforward API. This framework will avoid external dependencies to ensure ease of use and integration.

## Consequences

### Positive:

- **Simplicity**: A minimalistic API will make the framework easier to learn and use, reducing the learning curve for new developers.
- **No External Dependencies**: By avoiding external dependencies, the framework will be easier to integrate and maintain, reducing potential conflicts and bloat.
- **Performance**: A lightweight framework can offer better performance due to reduced overhead.
- **Control**: Greater control over the framework's features and behavior, ensuring it meets the specific needs of the project.

### Negative:

- **Feature Limitations**: The framework may lack some advanced features found in more comprehensive mocking frameworks.
- **Development Effort**: Additional effort will be required to develop and maintain the new framework.
- **Adoption**: Convincing developers to switch to a new framework may be challenging, especially if they are accustomed to existing solutions.
41 changes: 41 additions & 0 deletions docs/ADR/DocumentationAndExamples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Approach to Documentation and Examples

## Context

Effective documentation and examples are crucial for the adoption and proper use of any framework. Clear and concise documentation helps developers understand the framework's features and usage. Providing relevant examples can further illustrate how to implement and utilize the framework in real-world scenarios.

## Decision

We will create concise documentation and examples for the MiniMock framework. The documentation will cover essential aspects of the framework, including installation, configuration, and usage. Examples will be provided to demonstrate common use cases.

## Status

Accepted

## Consequences

### Positive:

- **Clarity**: Clear and concise documentation will help developers understand how to use the framework effectively.
- **Adoption**: Good documentation and examples can increase the adoption rate of the framework.
- **Support**: Reduces the need for support by providing answers to common questions and issues.
- **Consistency**: Ensures consistent usage of the framework across different projects.

### Negative:

- **Effort**: Requires effort to create and maintain concise documentation and examples.
- **Maintenance**: Documentation must be kept up-to-date with any changes or updates to the framework.

## Documentation Structure

1. **Introduction**: Overview of the framework, its purpose, and key features.
2. **Getting Started**: Instructions on how to install and configure the framework.
3. **Usage Guide**: Detailed guide on how to use the framework, including API references.
4. **Examples**: Practical examples demonstrating common use cases.
5. **FAQ**: Frequently asked questions and troubleshooting tips.

## Examples

- **Basic Mocking**: Simple example showing how to create and use a mock.
- **Advanced Mocking**: Examples of more complex scenarios, such as mocking protected methods and handling asynchronous methods.
- **Integration**: Examples showing how to integrate the framework with other tools and libraries.
22 changes: 22 additions & 0 deletions docs/ADR/HowStrictShouldMiniMockBe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Decision on How Strict the Framework Should Be

## Context

In the MiniMock framework, there is a need to determine the level of strictness when handling calls to members that are not explicitly mocked. A strict framework can help catch unintended calls and ensure that tests are precise and reliable. However, events are a special case and should not require listeners when they are called.

## Decision

The framework will be strict, throwing exceptions when a member that is not mocked is called. This approach ensures that all interactions are explicitly defined and helps catch unintended calls. However, events will be treated as a special case and will not require listeners when they are called.

## Consequences

### Positive:

- **Precision**: Ensures that all interactions with mocks are explicitly defined, leading to more precise and reliable tests.
- **Error Detection**: Helps catch unintended calls to members that are not mocked, reducing the risk of false positives in tests.
- **Consistency**: Provides a consistent approach to handling calls to non-mocked members.

### Negative:

- **Strictness**: The strict approach may require more effort to set up mocks, as all interactions must be explicitly defined.
- **Event Handling**: Special handling for events may introduce some complexity in the framework.
54 changes: 54 additions & 0 deletions docs/ADR/LoggingAndDebugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Approach to Logging and Debugging

## Context

Effective logging and debugging are essential for the development and maintenance of the MiniMock framework. Logging helps track the setup and usage of mocks, while debugging aids in identifying and resolving issues. To make debugging tests smoother, the `DebuggerStepThrough` attribute will be used to skip over the internal framework code during debugging sessions.

## Decision

We will implement logging to capture events related to the setup of mocks and calls to the mocks. Additionally, the `DebuggerStepThrough` attribute will be applied to relevant parts of the framework to streamline the debugging process. Logging functionality will be planned but not yet implemented.

## Status

Accepted

## Consequences

### Positive:

- **Traceability**: Logging provides a trace of mock setup and usage, aiding in troubleshooting and analysis.
- **Smooth Debugging**: The `DebuggerStepThrough` attribute helps developers focus on their test code rather than the internal workings of the framework.
- **Insight**: Logs offer insights into the behavior and interactions within the framework.

### Negative:

- **Implementation Effort**: Requires effort to implement and maintain logging functionality.
- **Performance Overhead**: Logging may introduce a slight performance overhead.

## Implementation Plan

1. **Logging**: Plan and design the logging mechanism to capture mock setup events and calls to mocks.
2. **DebuggerStepThrough**: Apply the `DebuggerStepThrough` attribute to relevant methods and classes to improve the debugging experience.

## Example

```csharp
[System.Diagnostics.DebuggerStepThrough]
public void SetupMock()
{
// Setup mock logic
Log("Mock setup completed.");
}

[System.Diagnostics.DebuggerStepThrough]
public void CallMock()
{
// Call mock logic
Log("Mock method called.");
}

private void Log(string message)
{
// Placeholder for logging implementation
Console.WriteLine(message);
}
22 changes: 22 additions & 0 deletions docs/ADR/MatchingTargetApi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Matching Target API in Mock API

When creating a mocking class, the mock API must closely mirror the API of the target being mocked. This ensures that the mock can be used as a drop-in replacement for the target, facilitating seamless testing and reducing the learning curve for developers.

## Decision

The mock API should reflect the target API with minimal additional methods. The mock should only include methods that already exist in the target API, ensuring consistency and ease of use.

## Status

Accepted

## Consequences

### Positive:
- Developers can use the mock without learning a new API.
- Tests are more readable and maintainable as they closely resemble the actual code.
- Reduces the risk of errors due to API mismatches.

### Negative:
- Limited flexibility in extending the mock API for advanced testing scenarios.
- May require more effort to implement certain mocking features without additional methods.
22 changes: 22 additions & 0 deletions docs/ADR/NoBuiltInAssertionFeature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# No Built-in Assertion Feature

## Context

In our mocking framework, there is a consideration to include a built-in assertion feature. However, there are numerous assertion frameworks available, each with its own strengths and user base. Including a built-in assertion feature may lead to redundancy and limit the flexibility for users to choose their preferred assertion framework.

## Decision

We will not include a built-in assertion feature in our mocking framework. Instead, we will rely on users to choose and use their preferred assertion framework.

## Consequences

### Positive:

- **Flexibility**: Users can choose the assertion framework that best fits their needs and preferences.
- **Simplicity**: Reduces the complexity of the mocking framework by not including redundant features.
- **Interoperability**: Ensures compatibility with a wide range of existing assertion frameworks.

### Negative:

- **Learning Curve**: Users may need to learn and integrate a separate assertion framework if they are not already familiar with one.
- **Dependency Management**: Users will need to manage additional dependencies for their chosen assertion framework.
24 changes: 24 additions & 0 deletions docs/ADR/NoDependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# No Dependencies to Shared Libraries

## Context

In our project, there is a consideration to include dependencies on shared libraries. However, relying on shared libraries can introduce several challenges, including version conflicts, increased complexity, and reduced control over the project's dependencies.

## Decision

We will not include any dependencies on shared libraries in our project. Instead, we will aim to implement necessary functionality within the project itself or use static linking where appropriate.

## Consequences

### Positive:

- **Control**: Greater control over the project's dependencies and versions.
- **Simplicity**: Reduces the complexity of managing external dependencies.
- **Stability**: Minimizes the risk of version conflicts and compatibility issues.
- **Security**: Reduces the attack surface by limiting external dependencies.

### Negative:

- **Development Effort**: May require additional effort to implement functionality that would otherwise be provided by shared libraries.
- **Code Duplication**: Potential for code duplication if similar functionality is needed across multiple projects.
- **Maintenance**: Increased maintenance burden as all functionality must be maintained within the project.
42 changes: 42 additions & 0 deletions docs/ADR/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Architecture Decision Records (ADR)

Architecture Decision Records (ADRs) are documents that capture important architectural decisions made during the development of a MiniMock.

All the ADRs have been approved and are considered final decisions for the project.

## General ADRs

- [Do We __Really__ Need a New Mocking Framework?](DoWeNeedANewMockingFramework.md) - Deciding whether to build a new mocking framework.
- [Matching Target API in Mock API](MatchingTargetApi.md) - Ensures the mock API closely mirrors the target API.
- [How Strict Should MiniMock Be?](HowStrictShouldMiniMockBe.md) - Deciding how strict the framework should be.
- [No Built-in Assertion Feature](NoBuiltInAssertionFeature.md) - Users choose their preferred assertion framework.
- [No Dependencies to Shared Libraries](NoDependencies.md) - Avoid dependencies on shared libraries.
- [Documentation and Examples](DocumentationAndExamples.md) - Approach to documentation and examples for the framework.
- [Logging and Debugging](LoggingAndDebugging.md) - Approach to logging and debugging within the framework.
- [Allowing Skipping Arguments in Mock Setup](SupportSkippingArguments.md) - Allows skipping arguments in mock setups for flexibility.
- [Creating Mocks](CreatingMocks.md) - Decision on how to create mocks in the framework.

## Feature Specific ADRs

- [Support for Classes and Interfaces](feature/SupportForClassesAndInterfaces.md) - Decision on supporting classes and interfaces in the mocking framework.
- [Support for Constructors](feature/SupportForConstructors.md) - Decision on supporting constructors in the mocking framework.
- [Support for Methods](feature/SupportForMethods.md) - Decision on supporting methods in the mocking framework.
- [Support for Properties](feature/SupportForProperties.md) - Decision on supporting properties in the mocking framework.
- [Support for Events](feature/SupportForEvents.md) - Decision on supporting events in the mocking framework.
- [Support for Indexers](feature/SupportForIndexers.md) - Decision on supporting indexers in the mocking framework.
- Special cases
- [Support for Protected Methods](feature/SupportingProtectedMethods.md) - Decision on whether to support mocking protected methods.
- [Support for Generic Methods (WIP)](feature/SupportForGenericMethods.md) - Decision on supporting generic methods in the mocking framework.
- [Support for Asynchronous Methods (WIP)](feature/SupportForAsynchronousMethods.md) - Handling asynchronous methods in the mocking framework.
- [Support for Virtual Methods (WIP)](feature/SupportForVirtualMethods.md) - Decision on supporting virtual methods in the mocking framework.
- [Support for Overloads (WIP)](feature/SupportForOverloads.md) - Decision on supporting method overloads in the mocking framework.
- [Support for Out and Ref Parameters (WIP)](feature/SupportForOutAndRefParameters.md) - Decision on supporting out and ref parameters in the mocking framework.
- [Support for Internal Methods (WIP)](feature/SupportForInternalMethods.md) - Decision on supporting internal methods in the mocking framework.
- [Support for Abstract Classes (WIP)](feature/SupportForAbstractClasses.md) - Decision on supporting abstract classes in the mocking framework.
- [Support for Delegates (WIP)](feature/SupportForDelegates.md) - Decision on supporting delegates in the mocking framework.

## Unsupported Features

- [Support for Extension Methods (WIP)](Unsupported/SupportForExtensionMethods.md) - Decision on supporting extension methods in the mocking framework.
- [Support for Sealed Classes (WIP)](Unsupported/SupportForSealedClasses.md) - Decision on supporting sealed classes in the mocking framework.
- [Support for Static Members (WIP)](Unsupported/SupportForStaticMembers.md) - Decision on supporting static members in the mocking framework.
21 changes: 21 additions & 0 deletions docs/ADR/SupportSkippingArguments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Allowing Skipping Arguments in Mock Setup

## Context

In our mocking framework, we have the option to skip arguments when setting up mocks for methods. Although this feature has been found to be rarely used, it can provide significant flexibility and convenience in certain testing scenarios.

## Decision

We will allow the skipping of arguments when setting up mocks for methods. This will enable developers to focus on the relevant arguments and simplify the mock setup process when certain arguments are not needed for specific tests.

## Consequences

### Positive:
- **Flexibility**: Provides greater flexibility in setting up mocks, allowing developers to skip irrelevant arguments.
- **Convenience**: Simplifies the mock setup process, especially for methods with many parameters.
- **Focus**: Allows tests to focus on the relevant arguments, improving readability and maintainability.

### Negative:
- **Clarity**: May reduce the clarity of tests if arguments are skipped without proper documentation.
- **Consistency**: Could lead to inconsistent mock setups across the codebase if not used judiciously.
- **Error Potential**: Increases the risk of errors if skipped arguments are assumed incorrectly.~~~~
23 changes: 23 additions & 0 deletions docs/ADR/feature/SupportForClassesAndInterfaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Decision on Supporting Classes and Interfaces

## Context

In the MiniMock framework, there is a need to determine the scope of support for mocking different types of members. While interfaces are the primary focus due to their flexibility and common usage in dependency injection, there is also a need to support classes to cover a broader range of use cases.

## Decision

The MiniMock framework will primarily focus on supporting interfaces but will also include support for classes. This approach ensures that the framework can be used in a wide variety of scenarios, providing flexibility and comprehensive mocking capabilities.

## Consequences

### Positive:

- **Flexibility**: Supports a wide range of use cases by allowing both interfaces and classes to be mocked.
- **Comprehensive**: Provides a robust mocking solution that can handle various types of dependencies.
- **Usability**: Makes the framework more versatile and useful for developers.

### Negative:

- **Complexity**: Adding support for classes may introduce additional complexity in the framework.
- **Maintenance**: Requires ongoing maintenance to ensure both interfaces and classes are supported effectively.
f mocking scenarios.
24 changes: 24 additions & 0 deletions docs/ADR/feature/SupportForConstructors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Decision on Supporting Constructors

## Context

In the MiniMock framework, there is a need to determine the scope of support for mocking constructors. Initially, the framework will support only classes with parameterless constructors. This decision simplifies the initial implementation and allows for a gradual introduction of more complex constructor support.

## Decision

The MiniMock framework will initially support mocking only classes with parameterless constructors. A plan for adding support for classes with parameterized constructors is being developed and will be implemented in future iterations.

Since the main focus of the framework is to provide a simple and easy-to-use mocking solution for interfaces and classes, the decision to start with parameterless constructors aligns with this goal. See ADR [Support For Classes and Interfaces](SupportForClassesAndInterfaces.md) for more information.

## Consequences

### Positive:

- **Simplicity**: Simplifies the initial implementation by focusing on parameterless constructors.
- **Incremental Development**: Allows for a phased approach to adding more complex constructor support.
- **Usability**: Provides immediate value by supporting a common use case.

### Negative:

- **Limited Scope**: Initial support is limited to classes with parameterless constructors, which may not cover all use cases.
- **Future Work**: Additional effort will be required to implement support for parameterized constructors.
Loading

0 comments on commit 2320298

Please sign in to comment.